IEEE 754浮点数不能准确表示的第一个整数是哪个?


162

为了清楚起见,如果我使用的是实现IEE 754浮点数的语言,则我声明:

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

...然后将它们打印出来,我将得到0.0000和1.0000-准确。

但是,IEEE 754不能表示真实数字中的所有数字。接近零,“间隙”很小;随着距离的增加,差距会越来越大。

因此,我的问题是:对于IEEE 754浮点数,它是无法精确表示的第一个(最接近零)整数吗?我现在只真正关心32位浮点数,尽管如果有人给我64位的答案,我将很感兴趣!

我认为这很简单,只需计算2个bits_of_mantissa并加1,其中bits_of_mantissa是标准公开的位数。我是在我的机器(MSVC ++,Win64)上针对32位浮点数执行此操作的,但看起来还不错。


如果要一个无法代表的数字,为什么还要加一个?您使用或获得了多少电话?这是家庭作业吗?您的问题标题为“整数”,但您的问题为“ float”。
msw

5
因为我认为最大尾数会给我最大的可表示数字。2 ^ 22。不,这是一个好奇心问题。即使我知道有问题的int总是很小,我也总是感到内gui。我想知道上限是多少。据我所知,标题和问题是相同的,只是措辞不同。
Floomi



1
@KyleStrand已还原^ 2。我不知道为什么一个人对我来说比当时更正确。现在,与“…是位数…”相比,它们看起来都很尴尬
Pascal Cuoq

Answers:


211

2个尾数位+ 1 + 1

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

因此,无法精确表示并且将被舍入的第一个整数是:
For float,16,777,217(2 24 +1)。
对于double,9,007,199,254,740,993(2 53 +1)。

>>> 9007199254740993.0
9007199254740992

我声明了a float并将其设置为16,777,217。但是当我使用cout它打印时,结果为16,777,216。我正在使用C++。为什么我不能得到16,777,217?
硝酸钠

18
@sodiumnitrate检查问题标题。16777217是第一个不能精确表示的整数。
kennytm

好,谢谢。我很困惑,对此感到抱歉。我还有一个问题:16777216之后,下一个可表示的整数不应该是2 * 16777216吗?当我运行一个类似的计划,我将2 16777126.获得16777218
硝酸钠

5
下一个整数确实是16777218,因为2现在成为最后一个有效的二进制数字。
kennytm

6
在C ++中,是(1 << std::numeric_limits<float>::digits) + 1,在C中,是 (1 << FLT_MANT_DIG) + 1。前者很好,因为它可以是模板的一部分。如果您只想要可表示的最大整数,则不要加+1。
亨利·施莱纳

38

n位整数可表示的最大值是2 n -1。如上所述,a float的有效位数为24位,这似乎暗示2 24不适合。

但是

指数范围内的2的幂可以精确表示为1.0×2 n,因此2 24 可以拟合,因此第一个不可表示的整数float是2 24 +1。如上所述。再次。


1
这清楚地解释了另一个“额外的隐式精度”部分。谢谢。
chappjc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.