>>> 0.4-0.3 结果为啥是 0.10000000000000003
Cuick opened this issue · comments
知道了
虽然 @Cuick 已经找到了答案,写一下自己的理解:
[ins] In [14]: from decimal import *
[ins] In [15]: getcontext().prec
Out[15]: 28
[ins] In [16]: Decimal.from_float(0.3)
Out[16]: Decimal('0.299999999999999988897769753748434595763683319091796875')
[ins] In [17]: Decimal.from_float(0.1 + 0.2)
Out[17]: Decimal('0.3000000000000000444089209850062616169452667236328125')
[ins] In [18]: 0.3
Out[18]: 0.3
[ins] In [19]: 0.1 + 0.2
Out[19]: 0.30000000000000004
上面代码直接展示了0.1+0.2
和0.3
不是同一个东西,这不只是Python
中的情况,可以说绝大多数编程语言的浮点数在这个问题上都是一致的。
[16]
的输出是直接把0.3
转换成二进制表示对应的十进制的值[17]
的输出是分别把0.1
和0.2
转换成二进制表示相加之后对应的十进制的值[18]
的输出对应[16]
[19]
的输出对应[17]
,这个很直接二者都有0.30000000000000004
也就是说在Python
解释器中直接输入0.3
,其实际的二进制对应的值是0.3000000000000000444089209850062616169452667236328125
,然后解释器print
的时候肯定不是全部输出而是要round
一下,那输出几位呢?原则就是**在没有引起混乱的情况下,输出的位数就尽量短`。
为什么这么说呢?
因为不是所有的浮点数都有二进制的精确表示,并且浮点数的二进制位数有限制,所以会存在多个浮点数对应一个二进制的情况(实际就是一个浮点数二进制对应了实数域的一个连续区间,该区间内的浮点数都会映射到这个二进制表示),比如:
[ins] In [23]: Decimal.from_float(0.30000000000000003) # 和0.1+0.2对应的一样,也就是输入和输出不一样
Out[23]: Decimal('0.3000000000000000444089209850062616169452667236328125')
上面那个不引起混乱的规则就是将输出的值反过来代入Decimal.from_float
之后还必须是0.3000000000000000444089209850062616169452667236328125
而不能是其他的值(还能映射回那个二进制)。而0.3000000000000000444089209850062616169452667236328125
,不引起混乱的最短打印值(输出位数尽量短规则)就是round到0.30000000000000004
位数再少就变成了0.3000000000000000
也就是0.3
,这个就换成二进制就是[16]
的输出了。
ref
二进制表示浮点数会有截断误差 就是精度的问题 是正常的
问题是 如果我们想比较 0.1+0.2 之后的数值是否和0.3相等
也就是说从程序员的角度看 他们应该是相等的 输出是true
但是如果从计算机的角度看他们可能不等 那怎么解决呢?