为什么所有带有几位数字的小数点都能正确打印?

How comes all decimals with a few digits are printed correctly?

提问人:Weier 提问时间:6/14/2023 最后编辑:Weier 更新时间:6/15/2023 访问量:50

问:

众所周知,计算机以近似的方式将浮点数存储在有限内存上(参见 IEEE 754)。

这会导致奇怪的行为,例如(在 Python 中,但这应该无关紧要):

>>> 0.1 + 0.2
0.30000000000000004

>>> 0.10000000000000001
0.1

但是,当我们打印带有“几个”数字的数字时,例如 、 ...我们永远不会以数字的近似值结束(在我上面的第二个示例中,反之亦然:呈现为 )。0.10.20.30.100000000000000010.1

IEEE 754(或 Python,如果此行为是由于 Python 实现)如何实现这一点?

Python 数学 浮点 IEEE-754

评论

0赞 John Coleman 6/14/2023
您的问题尚不清楚,似乎是基于 IEEE 754 如何表示数字以及 Python 在打印或在 shell 中显示它时如何格式化它之间的混淆。
0赞 Xiidref 6/14/2023
它可能与 IEEE 754 的舍入规则有关,但我不确定确切的过程
0赞 Weier 6/14/2023
@JohnColeman我不能清楚这是由于 Python 渲染还是 IEEE 754 的一些细节,因为这正是我问题的重点,要问这种行为来自哪里。
0赞 Tim Roberts 6/15/2023
convert-string-to-float 和 convert-float-to-string 过程是可逆的。如果从字符串 开始,则转换为浮点近似值,该近似值将转换回 .当您进行算术运算时,这会导致舍入误差,因此会导致二进制值与转换为浮点数不同的二进制值。你的被截断了,因为没有足够的位来保存最后的 1。它丢失了。0.120.120.1+0.20.30.10000000000000001

答:

4赞 Eric Postpischil 6/15/2023 #1

Python 没有正式的规范,但一些 Python 实现使用一种算法将浮点数转换为字符串,该算法生成有效位数最少的十进制数字,因此将十进制数字转换回浮点数会产生浮点数。

当 .1 转换为 IEEE-754 双精度 (binary64) 时,结果是 binary64 中可表示的最接近的值,即 0.10000000000000000055511151231257827021181583404541015625。将其转换为字符串时,最少的数字算法会生成“0.1”,因为 .1 是最短的十进制数字,因此将其转换为 binary64 会产生 0.10000000000000000055511151231257827021181583404541015625。

因此,最少位数算法的一个固有属性是,如果你从一个没有“太多”数字的十进制数字 d 开始到一个浮点数 f,那么最少数字算法将产生数字 d,除了外观上的差异,比如在“.1”之前使用美学前导 0。

评论

0赞 Mark Ransom 6/15/2023
应该说,最少位数算法并非微不足道,需要一些工作才能完善。
0赞 Weier 6/15/2023
答案很清楚,谢谢!(对于那些感兴趣的人,我在 cPython 中找到了相关部分:github.com/python/cpython/blob/......)