IEEE 754浮点数中第一个无法准确表示的整数是多少?

233

为了更清晰地说明,如果我在使用一个实现IEEE 754浮点数的语言,并声明:

float f0 = 0.f;
float f1 = 1.f;

如果我对一个IEEE 754浮点数执行操作(比如加、减或乘),然后将它们打印出来,我会得到0.0000和1.0000——完全一致。

但是IEEE 754不能表示实数线上的所有数字。接近零时,“间隙”很小;当你远离零时,这些间隙变得越来越大。

因此,我的问题是:对于一个IEEE 754浮点数,哪个是第一个(最接近零)无法精确表示的整数?目前我只关心32位浮点数,不过如果有人提供64位浮点数的答案,我也会感兴趣!

我认为这应该很简单,只需要计算2bits_of_mantissa并加1,其中bits_of_mantissa是标准暴露出的位数。我在我的机器上(MSVC++,Win64)对32位浮点数进行了这样的计算,似乎没有问题。


7
因为我认为最大化尾数将给出最高可表示的数字。2^22。不,这是一个好奇的问题。即使我知道所讨论的整数非常小,但我总觉得在浮点数中放置整数有些不妥。我想知道上限是多少。就我所知,标题和问题是相同的,只是措辞不同。 - Floomi
1
这是一个关于在Double类型中能存储最大整数的问题,原文链接:https://dev59.com/G3I-5IYBdhLWcg3wc3-w 。 - FrankH.
1
@KyleStrand 撤销了^2。我不知道为什么当时一个看起来比另一个更正确。现在与“...是位数的数量…”相比,它们都显得笨拙。 - Pascal Cuoq
@PascalCuoq 感谢您再次考虑此事并做出更改!我同意,“the number”是更好的措辞。 - Kyle Strand
显示剩余3条评论
2个回答

293

2的幂指数(尾数位数+1)中的+1,是因为如果尾数包含abcdef...,它表示的数字实际上是1.abcdef... × 2^e,提供了额外的隐含位精度。

因此,第一个无法准确表示并将被舍入的整数为:

  • 对于32位浮点数,为16,777,217(224 + 1)。
  • 对于64位浮点数,为9,007,199,254,740,993(253 + 1)。

以下是使用64位浮点数的CPython 3.10的示例:

>>> 9007199254740993.0
9007199254740992.0

3
我声明了一个浮点数并将它设置为16,777,217。但是,当我使用“cout”输出它时,结果是16,777,216。我正在使用C++。为什么我无法得到16,777,217? - sodiumnitrate
37
@sodiumnitrate,请检查问题标题。16777217是第一个无法被精确表示的整数。请注意,这里的"incapable"意为"无法"或"不能"的意思。 - kennytm
6
下一个整数确实是16777218,因为2现在成为了最后一位有效的二进制数字。 - kennytm
9
在C++中,这是(1 << std::numeric_limits<float>::digits) + 1,在C语言中是(1 << FLT_MANT_DIG) + 1。前者适合作为模板的一部分使用。如果只想得到最大可表示整数,则不要添加+1。 - Henry Schreiner
2
你可以使用这个工具来检查浮点数的位表示,并找到最小/最大整数值:https://www.h-schmidt.net/FloatConverter/IEEE754.html 这里还有一个用于16、32、64和128位浮点数的工具:http://weitz.de/ieee/ - Zack Morris
显示剩余8条评论

53
n 位整数所能表示的最大值为 2n-1。如上所述,一个 float 在尾数上有 24 个二进制位的精度,似乎意味着 224 不会适合。

然而.

在指数范围内的 2 的幂次方可以被表示为 1.0×2n,所以 224 是可以 表示的,因此 float 的第一个不能表示为精确值的整数是 224+1。如上所述。再次说明。

4
这清楚地解释了另一个部分中“额外的隐式精度位”的含义。谢谢。 - chappjc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接