浮点运算:求和与乘法的误差 [英] Floating point arithmetic: summation versus multiplication of error
问题描述
我试图理解这个简单例子背后的浮点运算。两个代码在理论上算术上是等价的,但显然一系列的加法比单纯的乘法增加了更多的误差。
s = 0.0
在范围内(10):
s + = 0.1
印刷品
print('%。30f'%s)
0.9999999999999999
0.999999999999999888977697537484
但是:
$ $ $ code $ s = 0.1
s * = 10
print(s)
print('%。30f'%s)
1.0
1.000000000000000000000000000000
我想了解幕后发生了什么。
据我所知,小数点的二进制表示形式从来都不准确,这可以通过以下方式来验证:
$ p $ print(0.1)
print('%。30f'%0.1)
0.1
0.100000000000000005551115123126
所以在一系列总和中,余数 5.55e-18
不断加在变量上,并且非常快地增长。然而,当乘法时,我预计同样的余数也会乘以,并且会增长,但是这不会发生。这是为什么?转换为二进制之前的任何优化?
它只是如何结果四舍五入(内部,二进制) 。 0.1 转换成
0.1000000000000000055511151231257827021181583404541015625
即
0.0001100110011001100110011001100110011001100110011001101
二进制。
将其乘以10 (1010二进制),你得到 55个有效位;四舍五入到53位,它等于1.0。 加上0.1十倍,你会经历一系列的舍入(你假设错误保持加起来的变量并且很快就会增长是错误的 - 为什么要加0.1减10小于1.0呢?)。如果您在每次迭代后打印完整的十进制值,您应该看到 即55位;四舍五入到53位它是 其中小数点是 小于0.6,尽管你可能预料会更大。 I'm trying to understand the floating point arithmetic behind this simple example. Both codes are arithmetically equivalent in theory, but obviously a series of additions adds more error than a simple multiplication. but: I would like to understand what is going on behind the scenes. I understand that the binary representation of the decimal 0.1 is never accurate, and that can be verified by: So in a sequence of summations, that remainder However, when multiplying, I'd expect that the same remainder is also multiplied and it would grow, but that doesn't happen. Why is that? Any sort of optimisation before converting to binary? It just has to do with how results are rounded (internally, in binary). 0.1 converts to which is Multiply that by 10 (1010 in binary) and you get That is 55 significant bits; rounded to 53 bits it equals 1.0. Add 0.1 ten times and you'll go through a sequence of roundings (your assumption that the error "keeps adding up to the variable and very quickly it grows" is wrong -- why would adding 0.1 ten times be less than 1.0 then?). If you print the full decimal values after each iteration and you should see Look at what happens between 0.5 and 0.6, for example. Add the internal binary values for 0.5 and 0.1 The answer is That is 55 bits; rounded to 53 bits it's which in decimal is 0.59999999999999997779553950749686919152736663818359375 which is less than 0.6, though you might have expected it to be greater. 这篇关于浮点运算:求和与乘法的误差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
$ b $ pre $ $ c $ 1.00000000000000000000000000000000000000000000000000
code pre >
0.1000000000000000055511151231257827021181583404541015625
$ p $例如,看看0.5到0.6之间的情况。添加0.5和0.1的内部二进制值
0.200000000000000011102230246251565404236316680908203125
0.3000000000000000444089209850062616169452667236328125
0.40000000000000002220446049250313080847263336181640625
0.5
0.59999999999999997779553950749686919152736663818359375
0.6999999999999999555910790149937383830547332763671875
0.79999999999999993338661852249060757458209991455078125
0.899999999999999911182158029987476766109466552734375
0.99999999999999988897769753748434595763683319091796875
0.1
+ 0.0001100110011001100110011001100110011001100110011001101 $ c
$ b $ p
$ b $ p
$ $ $ $ $ $ $ 0.1001100110011001100110011001100110011001100110011001101
pre $ code 0.10011001100110011001100110011001100110011001100110011
$ / code>
0.59999999999999997779553950749686919152736663818359375
s=0.0
for i in range(10):
s += 0.1
print(s)
print('%.30f' % s)
0.9999999999999999
0.999999999999999888977697537484
s=0.1
s *= 10
print(s)
print('%.30f' % s)
1.0
1.000000000000000000000000000000
print(0.1)
print('%.30f' % 0.1)
0.1
0.100000000000000005551115123126
5.55e-18
keeps adding up to the variable and very quickly it grows. 0.1000000000000000055511151231257827021181583404541015625
0.0001100110011001100110011001100110011001100110011001101
in binary. 1.000000000000000000000000000000000000000000000000000001
0.1000000000000000055511151231257827021181583404541015625
0.200000000000000011102230246251565404236316680908203125
0.3000000000000000444089209850062616169452667236328125
0.40000000000000002220446049250313080847263336181640625
0.5
0.59999999999999997779553950749686919152736663818359375
0.6999999999999999555910790149937383830547332763671875
0.79999999999999993338661852249060757458209991455078125
0.899999999999999911182158029987476766109466552734375
0.99999999999999988897769753748434595763683319091796875
0.1
+ 0.0001100110011001100110011001100110011001100110011001101
0.1001100110011001100110011001100110011001100110011001101
0.10011001100110011001100110011001100110011001100110011