[英]Floating Point Arithmetic error
我正在使用以下函数来近似函数的导数:
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))
为导数。 现在,根据谷歌和我的计算器
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)
。
浮点运算(以及整数运算和定点运算)具有一定的粒度:值只能改变一定的步长。 对于IEEE-754 64位二进制格式,该步长约为该值的2 -52倍(约2.22•10 -16 )。 这对于物理测量来说非常小。
) is not very large compared to the step size. 但是,当你使h非常小时,f( x )和f( x + )之间的差异与步长相比并不是很大。 差异只能是步长的整数倍。
. 当导数为d时 ,f( x )的变化约为h · 。 ) as well as possible in the floating-point format, the measured value of their difference must be a multiple of the step size s , so it must be round( h • / s )• s , where round( y ) is y rounded to the nearest integer. 即使您以浮点格式计算f( x )和f( x + ),它们的差值的测量值也必须是步长s的倍数,因此它必须是圆的( h • / s)的•s,其中轮(Y)为y取整到最接近的整数。 / s is smaller, so the effect of rounding it to an integer is relatively larger. 显然,当你使h变小时 , h • / s越小,因此将其舍入为整数的效果相对更大。
另一种观察方式是,对于给定的f( x ),在计算f( x )周围的值时存在一定量的误差。 )–f( x ) gets smaller, but the error stays the same. 当你使h变小时 ,f( x + )-f( x )变小,但误差保持不变。 因此,误差相对于h增加。
当您减去两个几乎相同的数字时,结果的精度远低于任何一个输入。 这降低了整体结果的精度。
假设你有以下两个数字,好到15个小数位:
1.000000000000001
- 1.000000000000000
= 0.000000000000001
看看发生了什么? 结果只有一个好数字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.