print('%.70f' % (0.2 + 0.1)) 输出中的 36 位补丁

The 36-digit patch in the output of print('%.70f' % (0.2 + 0.1))

我理解为什么 0.1 + 0.2 在 Python 3 中产生这个:

>>> 0.1 + 0.2
0.30000000000000004

...但我不明白为什么下面显示的输出中间有一段 36 位(大部分)非零数字:

>>> print('%.70f' % (0.2 + 0.1))
0.3000000000000000444089209850062616169452667236328125000000000000000000

我确实希望 0.1 + 0.2 和最接近 0.1 + 0.2 的二进制 IEEE 754 浮点数之间存在差异,但我不明白为什么这种差异会导致 36 位表示(大致对应于~120 位精度)。

我可以理解错误的精度是否小得多(< 53 位),或者具有(明显的)无限精度,这可能是由于评估算法的人为因素 '%.70f' % (0.2 + 0.1)。但是我无法理解会导致上面显示的 36 位补丁的错误。

您正在使用的 Python 实现显然使用 IEEE-754 binary64 作为浮点数。 (这很常见,但 Python 没有强制要求。)

在此格式中,数字表示为 2 的幂的倍数,其中使用的特定 2 的幂取决于数字的大小。 (浮点格式也以其他在数学上等同于此的方式描述,例如使用具有固定小数位数的有效数字而不是我在这里使用的整数倍数。此描述更容易解释在手。)

对于 .3 左右的数字,使用的两个的幂是 2−54.1.2 相加的结果,经过四舍五入以适应浮点数格式是 5404319552844596 次 2−54,即 5404319552844596 / 254.

那个数字,5404319552844596 / 254,正好是 0.3000000000000000444089209850062616169452667236328125。