使用离散方法计算导数

发布于 2024-07-14 13:43:47 字数 83 浏览 6 评论 0原文

我正在寻找一种使用离散且快速的方法来计算导数的方法。 由于现在我不知道方程的类型,因此我正在寻找类似于我们可以找到的积分方法的离散方法,例如欧拉方法。

I am looking for a method to compute a derivative using a discrete and fast method. Since now I do not know the type of equation I have, I am looking for discrete methods analog to the ones that we can find for the integral such as, the Euler method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

一个人的旅程 2024-07-21 13:43:47

我认为您正在寻找以点计算的导数。
如果是这种情况,这里有一个简单的方法可以做到这一点。 您需要知道一点的导数,例如a。 它由 h->0 的差商极限给出:

difference quotient

你实际上需要实现 limit 函数。 所以你:

  • 定义一个epsilon,设置得越小越精确,设置越大越快
  • 计算起始h中的差商,假设h=0.01,将其存储在f1
  • 现在DO-WHILE 循环:

    1- 将 h 除以 2(或除以 10,重要的是使其更小)
    2-再次计算与h的新值的差商,将其存储在f2
    3-设置diff = abs(f2-f1)
    4-分配f1 = f2
    5- 从点 1 开始重复 while (diff>epsilon)

  • 您最终可以返回 f1 (或 f2)作为 f'(a) 的值

记住:
您假设该函数在 a 中可微。
由于计算机可以处理的有限十进制数字的错误,您得到的每个结果都将是错误的,这是无法避免的。

python 中的示例:

def derive(f, a, h=0.01, epsilon = 1e-7):
    f1 = (f(a+h)-f(a))/h
    while True: # DO-WHILE
        h /= 2.
        f2 = (f(a+h)-f(a))/h
        diff = abs(f2-f1)
        f1 = f2
        if diff<epsilon: break
    return f2

print "derivatives in x=0"
print "x^2: \t\t %.6f" % derive(lambda x: x**2,0)
print "x:\t\t %.6f" % derive(lambda x: x,0)
print "(x-1)^2:\t %.6f" % derive(lambda x: (x-1)**2,0)

print "\n\nReal values:"
print derive(lambda x: x**2,0)
print derive(lambda x: x,0)
print derive(lambda x: (x-1)**2,0)

输出:

derivatives in x=0
x^2:         0.000000
x:       1.000000
(x-1)^2:     -2.000000


Real values:
7.62939453125e-08
1.0
-1.99999992328

由于仅使用结果的前 6 位数字,我第一次得到“精确”值,请注意我使用 1e-7 作为 epsilon。之后将打印 REAL 计算值,并且它们epsilon 的大小显然在数学上是错误的。

I think you are looking for the derivative calculated in a point.
If this is the case, here there is a simple way to do that. You need to know the derivative in a point, say a. It is given by the limit of the difference quotient for h->0:

difference quotient

You actually need to implement the limit function. So you:

  • Define an epsilon, set it more small to be more precise, bigger to be faster
  • calculate the difference quotient in a starting h, suppose h=0.01, store it in f1
  • Now in a DO-WHILE loop:

    1- divide h by 2 (or by 10, the important thing is to make it smaller)
    2- calculate again the difference quotient with the new value of h, store this in f2
    3- set diff = abs(f2-f1)
    4- assign f1 = f2
    5- repeat from point 1 while (diff>epsilon)

  • You can finally return f1 (or f2) as the value of your f'(a)

Remember:
You are assuming the function is differentiable in a.
Every result you will get will be wrong due of errors of the finite decimal digit your computer can handle, there is no escape from this.

Example in python:

def derive(f, a, h=0.01, epsilon = 1e-7):
    f1 = (f(a+h)-f(a))/h
    while True: # DO-WHILE
        h /= 2.
        f2 = (f(a+h)-f(a))/h
        diff = abs(f2-f1)
        f1 = f2
        if diff<epsilon: break
    return f2

print "derivatives in x=0"
print "x^2: \t\t %.6f" % derive(lambda x: x**2,0)
print "x:\t\t %.6f" % derive(lambda x: x,0)
print "(x-1)^2:\t %.6f" % derive(lambda x: (x-1)**2,0)

print "\n\nReal values:"
print derive(lambda x: x**2,0)
print derive(lambda x: x,0)
print derive(lambda x: (x-1)**2,0)

Output:

derivatives in x=0
x^2:         0.000000
x:       1.000000
(x-1)^2:     -2.000000


Real values:
7.62939453125e-08
1.0
-1.99999992328

The first time I've got "precise" value" because of using only the first 6 digits of the result, note I used 1e-7 as epsilon. The REAL calculated values are printed after that, and they are obviously mathematically wrong. The choose of how small epsilon is depends on how precise you want your results to be.

抱猫软卧 2024-07-21 13:43:47

在计算数值(“有限”)导数方面有相当多的理论(和既定实践)。 确保所有细节正确,让您相信结果,这并非易事。 如果有任何方法可以获得该函数的分析导数(使用笔和纸,或计算机代数系统,例如 Maple MathematicaSage,或 SymPy),这是由迄今为止最好的选择。

如果您无法获得解析形式,或者您不知道函数(只是它的输出),那么数值估计是您唯一的选择。 C 语言数值复习中的章节是一个好的开始。

There is quite a bit of theory (and established practice) in calculating numerical ("finite") derivatives. Getting all the details correct, such that you believe the result, is not trivial. If there's any way you can get the analytical derivative of the function (using pen and paper, or a computer algebra system such as Maple, Mathematica, Sage, or SymPy), this is by far the best option.

If you can't get the analytical form, or you don't know the function (just it's output), then numerical estimation are your only option. This chapter in Numerical Recipies in C is a good start.

慈悲佛祖 2024-07-21 13:43:47

一个简单的方法是计算您感兴趣的导数的每个点的 f 对小值的变化。例如,要计算 ∂f/∂x,您可以使用以下方法:

epsilon = 1e-8
∂f/∂x(x, y, z) = (f(x+epsilon,y,z) - f(x-epsilon, y, z))/(epsilon * 2);

y 中的其他偏项将类似和z。

为 epsilon 选择的值取决于 f 的内容、所需的精度、使用的浮点类型以及可能的其他因素。 我建议您使用您感兴趣的函数来尝试它的值。

A simple method is to compute the change in f over a small value for each point of the derivative you're interested in. For example, to compute ∂f/∂x, you could use this:

epsilon = 1e-8
∂f/∂x(x, y, z) = (f(x+epsilon,y,z) - f(x-epsilon, y, z))/(epsilon * 2);

The other partials would be similar in y and z.

The value chosen for epsilon depends on the contents of f, the precision required, the floating point type used, and probably other things. I suggest you experiment with values for it with functions you're interested in.

烈酒灼喉 2024-07-21 13:43:47

要进行数值微分(始终是近似值),有两种常见情况:

  1. 您有一种方法(算法、方程)来计算任意给定 x 处的 f(x) 值,或者
  2. 您有 f(x) 值在一组等距的 x 值(f(1)、f(1.5)、f(2) 等)处:

  1. 如果您有算法,那么您最好看看Andrea安布的回答*:
    1. 从 f(a+h) 和 f(ah) 的值开始,然后执行
      f'(a) = { f(a+h)-f(ah) } / 2h
      这被称为中心差异。
    2. 根据 Andrea 的回答,减小偏移 h 的大小,直到 f'(a) 停止变化。
    • 请注意,在未检查 2h 是否大于 0 的情况下,请勿除以 2h,否则会出现除以零的错误。
  2. 如果函数的值位于 f(x) = f(xn) = fn 的一组值处,那么我们可以执行类似于上述方法,但我们的准确性将受到 xn 的值及其之间的差距的限制。
  3. 第一个近似只是使用与上面相同的中心差分算子;
    f'n = (fn+1 - fn-1)/2h,
    其中 h 是 xn 值之间的相等间距。
  4. 接下来是使用 五点模板,尽管它只有 4 个系数:维基百科页面上有详细说明。 这使用从 fn-2 到 fn+2 的值: f'n = (-fn+2< /sub> + 8fn+1 - 8fn-1 +fn-2)/12h。
  5. 有使用更多点的高阶近似,但它们变得越来越难以计算收益递减,并且在数值上变得更加不稳定。
  6. **注意**:这些有限差分公式依赖于 f 与 xn-1≤ x ≤n+1 范围内多项式的形状大致相同。 对于像正弦波这样的函数,它们在计算导数时可能非常不准确。

*Andrea的答案使用前向差分算子{f(a+h) - f(a)}/h而不是中心差分算子{f(a+h) - f(ah)}/2h,但是前向差分算子在数值解中不太准确。

To do numerical differentiation, which is always an approximation, there are two common scenarios:

  1. You have a way (algorithm, equation) to calculate the value of f(x) at any given x, or
  2. You have the value of f(x) at a set of equally spaced values of x (f(1), f(1.5), f(2) etc):

  1. If you have the algorithm, then you are best looking at Andrea Ambu's answer*:
    1. Start with the values of f(a+h) and f(a-h) and do
      f'(a) = { f(a+h)-f(a-h) } / 2h
      This is known as a central difference.
    2. Reduce the size of the offset h until f'(a) stops changing, as per Andrea's answer.
    • Be careful that you don't divide by 2h without checking it is larger than 0 or you'll get divide by zero errors.
  2. If you have the value of the function at a set of values of f(x) = f(xn) = fn, then we can do something similar to the above method, but our accuracy will be limited by the values of xn and the gaps between them.
  3. The first approximation is just to use the same central difference operator as above;
    f'n = (fn+1 - fn-1)/2h,
    where h is the equal spacing between the values of xn.
  4. The next is to use a five-point stencil, although it has only 4 coefficients as detailed on that wikipedia page. This uses the values from fn-2 to fn+2: f'n = (-fn+2 + 8fn+1 - 8fn-1 +fn-2)/12h.
  5. there are higher order approximations using more points, but they get increasingly difficult to calculate for diminishing returns, and become more unstable numerically.
  6. **Note**: These finite-difference formulae rely on f being approximately the same shape as a polynomial in the range xn-1≤ x ≤n+1. For functions like sine waves, they can be quite bad at calculating the derivative to a good degree of accuracy.

* Andrea's answer uses the forward difference operator {f(a+h) - f(a)}/h instead of the central difference operator {f(a+h) - f(a-h)}/2h, but the forward difference operator is less accurate in numerical solutions.

绝不放开 2024-07-21 13:43:47

如果不使用像 Maple 这样的符号数学语言,你能做的最好的就是在不同的点上近似导数。 (然后插入,如果你需要一个函数。)

如果你已经有了你想要使用的函数,那么你应该使用 向后除差论坛,以及Richardson 外推 来改善您的错误。

另请记住,这些方法适用于一个变量的函数。 然而,每个变量的偏导数将其他变量视为常数。

Short of using a symbolic math language, like Maple, the best you can do is to approximate the derivative at various points. (And then interpolate, if you need a function.)

If you've already got the function you want to use, then you should use the backward divided-difference forumla, and Richardson extrapolation to improve your error.

Also keep in mind that these methods work on functions of one variable. However, partial derivatives of each variable treat the other variables as constants.

神经大条 2024-07-21 13:43:47

自动微分是执行此类操作的最准确且概念上最棒的方法。 只是稍微复杂一点。

Automatic differentiation is the most accurate and conceptually awesome way of doing this kind of thing. Just a bit more complicated.

自由范儿 2024-07-21 13:43:47

正式来说,不。 您要么描述离散函数的(偏)导数,要么要求一种数值方法来近似连续函数的(偏)导数。

离散函数没有导数。 如果您查看导数的 epsilon-delta 定义,您会发现您需要能够计算接近您想要导数的点的函数。 如果函数仅具有 x、y 和 z 整数值,则这是没有意义的。 因此,对于任何快速值,都无法找到离散函数的导数。

如果您想要一种数值方法精确计算连续函数的导数,那么您也运气不好。 导数的数值方法是启发式的,而不是算法式的。 没有任何数值方法可以保证精确的解。 幸运的是,存在许多好的启发方法。 Mathematica 默认使用 布伦特主轴法 的专用版本。 我建议您使用 GNU 科学库,它很好地实现了布伦特方法。 我的一门数学课程的全部成绩都归功于 GSL。 如果您喜欢的话,红宝石绑定非常好。 如果有必要,大多数数值微分库都有一些不同的方法可用。

如果你真的想要,我可以拿出一些示例代码。 让我知道。

Formally, no. Either you are describing the (partial) derivitives of discrete functions or you are asking for a numerical method to approximate the (partial) derivatives of continuous functions.

Discrete functions don't have derivatives. If you review the epsilon-delta definition of a derivative, you will see that you would need to be able to evaluate the function close to the point you want the derivative at. That doesn't make sense if the function only has values at integer values of x, y and z. So there is no way to find the derivative of a discrete function for any value of fast.

If you want a numerical method exactly calculate the derivatives of a continuous function, you're out of luck as well. Numerical methods for derivatives are heuristic, not algorithmic. There is no numerical method which guarantees an exact solution. Fortunately, there exist many good heuristics. Mathematica uses a specialized version of Brent's principle axis method by default. I would recommend you use the GNU Scientific Library, which has a very good implementation of Brent's method. I owe my entire grade in one of my math courses to the GSL. The ruby bindings are pretty good if that's your thing. If necessary, most numerical differentiation libraries have a handful of different methods available.

If you really want, I can whip out some sample code. Let me know.

ι不睡觉的鱼゛ 2024-07-21 13:43:47

我假设您的函数比您发布的简单函数更复杂,因为封闭式解决方案太简单了。

当您使用“离散”这个词时,我认为您需要“有限差异”。 您需要一些离散化来计算近似值。

Df/Dx ~ (f2-f1)/(x2-x1) 等

I'll assume that your function is more complex than the simple one you posted, because the closed-form solution is far too simple.

When you use the word "discrete" it makes me think you need "finite differences". You'll need some discretization to calculate the approximation.

Df/Dx ~ (f2-f1)/(x2-x1), etc.

歌入人心 2024-07-21 13:43:47

我希望这可能会有所帮助数值微分。

I hope this may be helpful NUMERICAL DIFFERENTIATION.

各自安好 2024-07-21 13:43:47

如果函数如您所指出的那样是线性的,那么导数是微不足道的。 'x' 的导数是 'a'; 关于“y”的导数是“b”,关于“z”的导数是“c”。 如果方程具有更复杂的形式,并且您需要一个代表解的公式而不是经验解,那么请提交更复杂的方程形式。

问候

If the function is linear as you have indicated then the derivatives are trivial. The derivative with respect to 'x' is 'a'; the derivative with respect to 'y' is 'b' and the derivative with respect to 'z' is 'c'. If the equation is of a more complex form and you need a formula representing the solution rather than an empirical solution, then please submit the more complex form of the equation.

Regards

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文