简单的答案是
3*0.1 != 0.3由于量化(舍入)误差(而
4*0.1 == 0.4乘以2的幂通常是“精确”运算)。Python试图找到
最短的字符串并将其舍入为所需的值 ,因此它可以显示
4*0.1为
0.4相等,但不能显示
3*0.1为,
0.3因为它们不相等。
您可以
.hex在Python中使用该方法查看数字的内部表示形式(基本上是 确切的 二进制浮点值,而不是以10为底的近似值)。这可以帮助解释幕后情况。
>>> (0.1).hex()'0x1.999999999999ap-4'>>> (0.3).hex()'0x1.3333333333333p-2'>>> (0.1*3).hex()'0x1.3333333333334p-2'>>> (0.4).hex()'0x1.999999999999ap-2'>>> (0.1*4).hex()'0x1.999999999999ap-2'
0.1是0x1.999999999999a乘以2 ^ -4。末尾的“ a”表示数字10-换句话说,二进制浮点数中的0.1 略大于
“精确”值0.1(因为最终的0x0.99舍入为0x0.a)。当您将其乘以4(2的幂)时,指数会上移(从2 ^ -4到2 ^
-2),但数字不变,所以
4*0.1 == 0.4。
但是,当乘以3时,0x0.99与0x0.a0(0x0.07)之间的微小差异会放大为0x0.15错误,在最后一个位置显示为一位错误。这导致0.1 * 3
略大于 0.3的舍入值。
Python 3的float
repr被设计为可 双向访问的 ,也就是说,显示的值应完全可转换为原始值(
float(repr(f)) ==f对于所有float
f)。因此,它无法显示
0.3和
0.1*3完全相同的方式,或两个 不同的 数字最终会往返后相同。因此,Python
3的
repr引擎选择显示一个带有轻微的明显错误的引擎。



