两个双精度数的商的精度

门西亚

假设我要在x = pi / 2处以数值计算f(x)= cos(x)的一阶导数。df / dx = -sin(x),因此为df / dx = -1。为此,我使用最简单的公式:

df / dx =(f(x + h)-f(x))/ h + O(h)。

O(h)是与h成正比的误差,因此,数学上O(h)随h变为零而变为零。我了解在计算机中情况有所不同。

我是否应该期望如果我使用的是双精度,这应该给我15到17个十进制有效数字,我应该能够将精确结果df / dx = -1.0乘以〜10 ^ -15?即我应该找到(df / dx)_numerical + 1.0〜10 ^ -15?

这是我发现的h的不同值的结果:

h值:

[0.0001, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]

(df / dx)_数字:

[-0.9999999983332231,
-0.9999999999898844,
-0.9999999999175667,
-1.0000000005838656,
-0.999999993922529,
-1.000000082740371,
-1.000000082740371]

这是预期的吗?为什么?为什么对于h = 10 ^ -5可获得最佳结果?

Sneftel

使用有限差分计算导数很容易失去意义问题是要减去的上下文,而不是要进行的除法。基本上,cos(x)-cos(x+delta)cos(x)cos(x+delta)都接近零时就可以正常工作...但是随着它们远离零(但仍然彼此接近),结果的精度将急剧下降。在某一点上,由于使用较小的增量而导致的精度提高将被重要性降低导致的精度下降所抵消。对您来说,这似乎发生在1e-5左右,但这不是根本(在该区域中,错误往往会反弹很多)。

关于如何进行数值稳定的有限差分的文章很多,但是第一法则是“不要对差分的微小性过于贪婪”。有关更深入(而不模糊)的信息,我可以推荐Forman Acton的(通常)有效数值方法

编辑:

抱歉,我忘了提到最重要的部分。分子中的重要性丧失很重要,但是分子中的重要性丧失x+h更为重要而且该部分实际上很容易修复。

随着x变大,近似值x+h变差(再次失去重要性)。基本上,您用于评估的步长与分母中的步长不匹配。但!由于您实际上并不关心的确切h,因此只需找出四舍五入h后最终使用的值x+h,然后在分母中使用该值即可。从本质上讲,你算算x2=x+h,然后h'=x2-x(Sterbenz定理)的计算h'是精确x >> h的,从而消除了特定的重要性损失。

示例代码:

import math

def calcDerivAt_orig(f, x, h):
    x1 = x
    x2 = x+h
    y1 = f(x1)
    y2 = f(x2)
    return (y2-y1)/h

def calcDerivAt_fixed(f, x, h):
    x1 = x
    x2 = x+h
    y1 = f(x1)
    y2 = f(x2)
    return (y2-y1)/(x2-x1)

for h in [0.0001, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]:
    dOrig = calcDerivAt_orig(math.cos, math.pi/2, h)
    origErr = abs(-1 - dOrig)
    dFixed = calcDerivAt_fixed(math.cos, math.pi/2, h)
    fixedErr = abs(-1 - dFixed)
    print("h = {}: origErr = {}, fixedErr = {}".format(h, origErr, fixedErr))

产生:

h = 0.0001: origErr = 1.66677693869e-09, fixedErr = 1.66666680457e-09
h = 1e-05: origErr = 1.01155750443e-11, fixedErr = 1.6666779068e-11
h = 1e-06: origErr = 8.24332824223e-11, fixedErr = 1.66644475996e-13
h = 1e-07: origErr = 5.83865622517e-10, fixedErr = 1.55431223448e-15
h = 1e-08: origErr = 6.07747097092e-09, fixedErr = 0.0
h = 1e-09: origErr = 8.27403709991e-08, fixedErr = 0.0
h = 1e-10: origErr = 8.27403709991e-08, fixedErr = 0.0

一点也不差。当然,我们在选择时作弊x=pi/2,因为cos(x)那里的值接近于零;x=1.5某程度上,由于h我最初描述的重要性下降,您仍然会看到错误随着缩小而迅速膨胀

h = 0.0001: origErr = 3.53519750529e-06, fixedErr = 3.5351976152e-06
h = 1e-05: origErr = 3.53675653653e-07, fixedErr = 3.53669118991e-07
h = 1e-06: origErr = 3.52831192041e-08, fixedErr = 3.53651797846e-08
h = 1e-07: origErr = 4.03034106089e-09, fixedErr = 3.44793649187e-09
h = 1e-08: origErr = 5.5453325265e-09, fixedErr = 5.1691428915e-10
h = 1e-09: origErr = 7.21702790862e-08, fixedErr = 1.03628251535e-08
h = 1e-10: origErr = 1.6659127966e-08, fixedErr = 6.58739718329e-08

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在C ++中添加两个大的双精度数

在函数中修改和返回两个浮点数(或双精度数)的最佳方法?

比较C#中小数位数不同的两个双精度数

MASM32函数,将两个双精度数字相乘并将其返回

等值的两个双精度数是否保证具有相同的位模式?

比较两个不同的双精度数时返回true

转换带有两个小数点的双精度数

使用Matlab将两个双精度数组连接成anx 1单元格数组

在Java中将两个整数转换为双精度

在 C++ 中添加两个双精度

比较JavaScript中的两个数字,事实是它们是双精度数,并且使用==或===?

CsvHelper 在地图中将双精度数舍入到两个位置

比较两个舍入为特定小数的双精度变量时,精度是否重要?

比较双精度数和零精度

如何获得第n个双精度数

C ++检查一个双精度数是否在另一个双精度数(。+ /-)的0.1之内

如何标准化两个IEEE754单精度数字的和?

如何在将其设为字符串之前从双精度数中删除最后两个数字?

将双精度对转换为双精度数组

如何在PHP中将两个以上的<br/>标记转换为双精度<br/> <br/>

如何使用Lambda表达式比较两个双精度值列表

检查两个浮点/双精度值是否完全相等

将两个双精度值的模与 Java 中的整数进行比较是否正确?

对SHUFPD或PSHUFD偏爱在XMM中反转两个压缩双精度字吗?

如何将两个整数相除以获得双精度?

在java中用两个小数点问题打印双精度

Java:检查两个双精度值是否匹配特定的小数位数

使用Java中的RegEx从字符串中提取两个双精度值

如何用256位AVX向量对两个复数双精度平方?