浮点运算错误

6

我正在使用以下函数来近似计算一个点处的函数导数:

def prime_x(f, x, h):

    if not f(x+h) == f(x) and not h == 0.0: 
        return (f(x+h) - f(x)) / h
    else:
        raise PrecisionError

作为一个测试,我将f传递为fx,将x传递为3.0。其中fx是:

def fx(x):

    import math
    return math.exp(x)*math.sin(x)

这有一个导数为exp(x)*(sin(x)+cos(x))的函数。根据Google和我的计算器:

exp(3)*(sin(3)+cos(3)) = -17.050059

到目前为止一切都很好。但是当我试着用小的h值测试函数时,我得到了以下结果:

print prime_x(fx, 3.0, 10**-5)
-17.0502585578
print prime_x(fx, 3.0, 10**-10)
-17.0500591423
 print prime_x(fx, 3.0, 10**-12)
-17.0512493014
print prime_x(fx, 3.0, 10**-13)
-17.0352620898
print prime_x(fx, 3.0, 10**-16)
__main__.PrecisionError: Mantissa is 16 digits

为什么当 h 减小(一定程度后)误差会增加?我本以为只要 f(x+h) 等于 f(x) ,误差就会减小。


3
如果你发现自己写了这样的代码:if not a and not b: do this else: do that,通常可以改为:if a or b: do that else: do this,这样不会让其他人阅读时感到困惑。 - askewchan
2
@askewchan,在这种情况下,建议更好,因为您可以完全省略else。您在if中处理错误情况,然后一旦通过,处理正常情况。 - Mark Ransom
2
点击此处获取有用的建议 ;-)](http://en.wikipedia.org/wiki/Numerical_differentiation#Practical_considerations_using_floating_point_arithmetic) - Tim Peters
2
这不应该被标记为重复;数值微分引起的错误与所谓的重复问题中的错误不同。有一个完整的数学领域研究当数值逼近用于计算时会发生什么,称为数值分析。简单地将所有数值精度问题归为“浮点数不准确”是不合理的。这些问题正在被研究,有方法来解决它们,存在着有趣的错误属性和模式,并且它们并不都相同。 - Eric Postpischil
2个回答

7
浮点算术(以及整数算术和定点算术)具有一定的粒度:值只能按照一定步长更改。对于IEEE-754 64位二进制格式,该步长约为值的2–52倍(约为2.22•10–16)。这对于物理测量来说非常小。
然而,当你使得h非常小时,f(x)和f(x+h)之间的差异与步长相比并不是很大。差异只能是步长的整数倍。
当导数为d时,f(x)的变化约为hd。即使在浮点格式中尽可能地计算f(x)和f(x+h),它们的差值的测量值也必须是步长s的倍数,因此它必须是round(hd/s)•s,其中round(y)是将y四舍五入到最近的整数。显然,随着h越来越小,hd/s也越来越小,因此将其舍入为整数的影响相对较大。
另一种看待这个问题的方法是,在给定f(x)的情况下,计算f(x)周围值的误差有一定范围。随着h的减小,f(x+h)–f(x)变得更小,但误差保持不变。因此,相对于h,误差会增加。

6
当你减去两个非常接近的数字时,结果的精度比任一输入的精度都要低。这会降低整体结果的精度。
假设你有以下两个数字,保留15位小数:
  1.000000000000001
- 1.000000000000000
= 0.000000000000001

看到发生了什么了吗?结果只有一位好的数字。

1
我总是发现演示像 1.0 - 1e-33 == 1.0 这样的东西很有说明性。尽管在数学上这不是“真的”,但 Python 认为它是“真的”,因为没有足够的精度来表示这些数字之间的小差异。在这种情况下,当你减去一系列产生相同(或非常相似)结果的 h 时,你可能会得到一系列广泛的值。当你将该数字除以 h 时,你可能会得到不精确的结果。 - mgilson
4
实际上,减去两个几乎相等的数在没有误差的情况下(假定采用IEEE 754标准)。减去两个几乎相等的数的结果具有与输入相同的精度(其有效数字中具有相同数量的位数)和相同的误差(与理想数学值的差异)。唯一改变的是相对误差,而这仅仅是因为您改变了相对于什么进行测量(结果是减法结果而不是输入)。 - Eric Postpischil
数值微分问题的更好视角是,当 h 很小时,f(x) 和 f(x+h) 的精度不足以包含有关它们之间差异的大量信息。当计算 f(x) 和 f(x+h) 时,这些信息已经丢失了。减法并不是问题;在减法中没有信息丢失。 - Eric Postpischil
1
@EricPostpischil,听起来你很想回答问题,我邀请你这样做。我试图用最简单的方式来表述问题,欢迎其他观点。编辑:我看到你在我提出建议之前就采纳了它! - Mark Ransom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接