简体   繁体   English

浮点算术错误

[英]Floating Point Arithmetic error

I'm using the following function to approximate the derivative of a function at a point: 我正在使用以下函数来近似函数的导数:

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

As a test I'm passing f as fx and x as 3.0. 作为测试,我将f传递为fxx传递为3.0。 Where fx is: 其中fx是:

def fx(x):

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

Which has exp(x)*(sin(x)+cos(x)) as derivative. 其中exp(x)*(sin(x)+cos(x))为导数。 Now, according to Google and to my calculator 现在,根据谷歌和我的计算器

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

So far so good. 到现在为止还挺好。 But when I decided to test the function with small values for h I got the following: 但是,当我决定与小值测试功能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

Why does the error increase when h decreases (after a certain point)? 当h减小时(某个点之后),为什么误差会增加? I was expecting the contrary until f(x+h) was equal to f(x) . 我期待相反,直到f(x+h)等于f(x)

Floating-point arithmetic (and integer arithmetic and fixed-point arithmetic) has a certain granularity: Values can only change by a certain step size. 浮点运算(以及整数运算和定点运算)具有一定的粒度:值只能改变一定的步长。 For IEEE-754 64-bit binary format, that step size is about 2 –52 times the value (about 2.22•10 –16 ). 对于IEEE-754 64位二进制格式,该步长约为该值的2 -52倍(约2.22•10 -16 )。 That is very small for physical measurements. 这对于物理测量来说非常小。

However, when you make h very small, the difference between f( x ) and f( x + h ) is not very large compared to the step size. 但是,当你使h非常小时,f( x )和f( x + h )之间的差异与步长相比并不是很大。 The difference can only be an integral multiple of the step size. 差异只能是步长的整数倍。

When the derivative is d , the change in f( x ) is about hd . 当导数为d时 ,f( x )的变化约为h · d Even if you calculate f( x ) and 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( hd / s )• s , where round( y ) is y rounded to the nearest integer. 即使您以浮点格式计算f( x )和f( x + h ),它们的差值的测量值也必须是步长s的倍数,因此它必须是圆的( hd / s)•s,其中轮(Y)y取整到最接近的整数。 Clearly, as you make h smaller, hd / s is smaller, so the effect of rounding it to an integer is relatively larger. 显然,当你使h小时hd / s越小,因此将其舍入为整数的效果相对更大。

Another way of looking at this is that, for a given f( x ), there is a certain amount of error in calculating values around f( x ). 另一种观察方式是,对于给定的f( x ),在计算f( x )周围的值时存在一定量的误差。 As you make h smaller, f( x + h )–f( x ) gets smaller, but the error stays the same. 当你使h小时 ,f( x + h )-f( x )变小,但误差保持不变。 Therefore, the error increases relative to h . 因此,误差相对于h增加。

When you subtract two numbers that are almost the same, the result has much less precision than either of the inputs. 当您减去两个几乎相同的数字时,结果的精度远低于任何一个输入。 This reduces the precision of the overall result. 这降低了整体结果的精度。

Suppose you have the following two numbers, good to 15 decimal places: 假设你有以下两个数字,好到15个小数位:

  1.000000000000001
- 1.000000000000000
= 0.000000000000001

See what happened? 看看发生了什么? The result only has one good digit. 结果只有一个好数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM