有人能解释一下这种浮点行为吗?

4 投票
3 回答
583 浏览
提问于 2025-04-16 14:24

受到这个问题的启发,我想弄清楚到底发生了什么(我的理解比较直观,但我不太明白为什么会这样)。

我认为问题的关键在于这个(运行的是64位的Python):

>>> sys.maxint
9223372036854775807
>>> float(sys.maxint)
9.2233720368547758e+18

Python使用的是IEEE 754浮点数表示法,这种表示法实际上有53位用于有效数字。不过,按照我的理解,上面例子中的有效数字需要57位(如果去掉隐含的前导1,则需要56位)才能表示。有人能解释一下这个差异吗?

3 个回答

1

当你把 sys.maxint 转换成浮点数(float 或 double)时,结果会是 0x1p63。这是因为它的有效数字只有 24 或 53 位(包括隐含位),所以后面的位数会导致四舍五入。(sys.maxint 是 2^63 - 1,四舍五入后变成 2^63。)

然后,当你打印这个浮点数时,有个小程序会把它格式化成十进制数字。为了做到这一点,它会计算出表示 2^63 的数字。能够打印出 9.2233720368547758e+18,并不意味着原来的数字和 9.2233720368547759e+18 有什么区别。这只是说明它的位数确实代表了 9.2233720368547758e+18(大约)。实际上,双精度浮点数中下一个可以表示的数字是 9223372036854777856(大约是 9.2233720368547778e+18),也就是 2^63 + 2048。因此,这些整数的低 11 位在浮点数中是不存在的。格式化程序只是把这个数字显示成好像那些位是零一样。

2

你错了。它只需要1个比特。

>>> (9.2233720368547758e+18).hex()
'0x1.0000000000000p+63'
6

也许下面的内容能帮助你更好地理解:

>>> hex(int(float(sys.maxint)))
'0x8000000000000000L'

这段代码显示,float(sys.maxint) 实际上是一个2的幂。所以,在二进制中,它的有效数字部分(也叫尾数)就是 1。在IEEE 754标准中,前面的 1. 是隐含的,因此在计算机内部表示这个数字时,它的有效数字部分全是零。

实际上,表示这个数字的IEEE位模式如下:

0x43E0000000000000

注意,只有前面三个“半字节”(即符号位和指数位)是非零的。有效数字部分完全由零组成。因此,它并不需要56位(实际上也不需要53位)来表示。

撰写回答