简单的答案是因为量化(舍入)误差导致3 * 0.1!= 0.3(而4 * 0.1 == 0.4,因为乘以2的幂通常是“精确”操作)。
您可以在Python中使用.hex方法来查看数字的内部表示(基本上,精确的二进制浮点值,而不是基本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被设计为可以往返的,也就是说,显示的值应该可以精确地转换为原始值。因此,它不能以完全相同的方式显示0.3和0.1 * 3,或者两个不同的数字在往返之后将结束相同。因此,Python 3的repr引擎选择显示一个有轻微的明显错误。