为什么不同的步长在逼近导数时会产生很大的数值误差?

问题描述

我正在尝试一些代码来帮助我逼近任意函数的导数。我看到另一个 post 上有四个选项:

  1. 有限差分
  2. 自动导数
  3. 符号微分
  4. 手动计算导数

我发现我的方法在第一个选项中效果最好,该选项带有“容易出现数值错误”的注释。所以我知道这种方法并不准确,这很好。

话虽如此,我对不同数据类型可以存储的大小数字进行了一些研究,并在此 post 中发现它可以非常小(大约 10–308 ) 和“在正常范围内,基本操作的结果将在格式的正常精度内准确”。

话虽如此,对于以下我探索不同大小间隔的代码片段,我似乎得到了非常糟糕的结果;最小的差异不应小于 10–27(10–9,立方),远大于极限值。我希望得到更具体的答复?

epsilon = 0.01 # is "small" w.r.t. to 3

def approx_derivative(func): # rough derivative factory function
  return lambda x : (func(x + epsilon) - func(x)) / epsilon

while epsilon > 10**-9:
  nth_deriv = lambda x : x ** 3 # 0th derivative
  for i in range(5): # should read about 27,27,18,6,0
    print(nth_deriv(3),end=',')
    nth_deriv = approx_derivative(nth_deriv) # take derivative
  print('\n')
  epsilon *= 0.1

输出为:

27,27.090099999999495,18.0599999999842,6.000000002615025,-3.552713678800501e-07,27.009000999996147,18.00600000123609,6.000000496442226,-0.007105427357601002,27.00090001006572,18.000599766310188,6.004086117172847,-71.05427357601002,27.000090000228735,18.000072543600254,3.5527136788005005,355271.36788005003,27.000009005462285,17.998047496803334,0.0,3552713678.8005,27.000000848431675,18.11883976188255,-35527136788004.99,27.0000001023618,3.552713678800497e+17,27.000002233990003,

正如我们在前几个示例中看到的,结果并不准确,但相当不错。但是,对于某些间隔大小,某些值会被放大;其他归0;有些是完全错误的,比如给出一半的值,尽管直觉认为它们应该对较小的 epsilon 变得更准确。我可以将哪些主要因素归因于此错误?我应该注意/注意什么?是否有我应该担心的错误(例如除以 0)?

epsilon 是否有一个通常被认为是使用浮点数进行计算的“最佳”值?或者是否有根据您的输入选择合适大小的 epsilon 的“经验法则”?是否有比我实现的导数更适合使用的导数定义?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)