浮点运算:求和与乘法的乘积

时间:2016-11-22 08:28:51

标签: floating-point date-arithmetic

我试图理解这个简单例子背后的浮点运算。这两个代码在理论上是算术等价的,但显然一系列的加法比简单的乘法增加了更多的误差。

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

我想了解幕后发生的事情。

据我所知,十进制0.1的二进制表示永远不准确,可以通过以下方式验证:

print(0.1)
print('%.30f' % 0.1)
0.1
0.100000000000000005551115123126

因此,在一系列求和中,余数5.55e-18不断增加变量并且很快就会增长。

然而,当乘以时,我预计相同的余数也会乘以它会增长,但这并不会发生。这是为什么?在转换为二进制文件之前的任何优化?

1 个答案:

答案 0 :(得分:2)

它只与舍入结果(内部,二进制)有关。 0.1 converts to

0.1000000000000000055511151231257827021181583404541015625

0.0001100110011001100110011001100110011001100110011001101 in binary

Multiply that乘以10(二进制1010),你得到

1.000000000000000000000000000000000000000000000000000001

这是55个有效位;四舍五入为53位,等于1.0。

添加0.1十次,你将经历一系列的舍入(你假设错误"不断增加变量并且很快就会增长"错误 - 为什么会添加0.1十次小于 1.0然后?)。如果在每次迭代后打印完整的十进制值,您应该看到

0.1000000000000000055511151231257827021181583404541015625
0.200000000000000011102230246251565404236316680908203125
0.3000000000000000444089209850062616169452667236328125
0.40000000000000002220446049250313080847263336181640625
0.5
0.59999999999999997779553950749686919152736663818359375
0.6999999999999999555910790149937383830547332763671875
0.79999999999999993338661852249060757458209991455078125
0.899999999999999911182158029987476766109466552734375
0.99999999999999988897769753748434595763683319091796875

例如,看一下0.5和0.6之间的情况。添加0.5和0.1

的内部二进制值

0.1 + 0.0001100110011001100110011001100110011001100110011001101

答案是

0.1001100110011001100110011001100110011001100110011001101

那是55位;四舍五入为53位

0.10011001100110011001100110011001100110011001100110011

以十进制表示

0.59999999999999997779553950749686919152736663818359375

小于0.6,尽管你可能期望它更大。