此答案假设
float
是以32位编码的IEEE-754单精度浮点数,并且一个
int
是32位的。有关IEEE-754的更多信息,请参见
此维基百科文章。
浮点数只有24位精度,而 int 有32位。因此,从0到16777215的 int 值在浮点数中具有精确表示,但大于16777215的数字不一定具有浮点数的精确表示。以下代码演示了这一事实(在使用IEEE-754的系统上)。
for ( int a = 16777210; a < 16777224; a++ )
{
float b = a;
int c = b;
printf( "a=%d c=%d b=0x%08x\n", a, c, *((int*)&b) );
}
期望的输出是
a=16777210 c=16777210 b=0x4b7ffffa
a=16777211 c=16777211 b=0x4b7ffffb
a=16777212 c=16777212 b=0x4b7ffffc
a=16777213 c=16777213 b=0x4b7ffffd
a=16777214 c=16777214 b=0x4b7ffffe
a=16777215 c=16777215 b=0x4b7fffff
a=16777216 c=16777216 b=0x4b800000
a=16777217 c=16777216 b=0x4b800000
a=16777218 c=16777218 b=0x4b800001
a=16777219 c=16777220 b=0x4b800002
a=16777220 c=16777220 b=0x4b800002
a=16777221 c=16777220 b=0x4b800002
a=16777222 c=16777222 b=0x4b800003
a=16777223 c=16777224 b=0x4b800004
有趣的是,float
值0x4b800002用于表示三个int
值16777219、16777220和16777221,因此将16777219转换为float
再转换回int
不会保留int
的精确值。
离INT_MAX
最近的两个浮点数值分别为2147483520和2147483648,可以通过以下代码演示:
for ( int a = 2147483520; a < 2147483647; a++ )
{
float b = a;
int c = b;
printf( "a=%d c=%d b=0x%08x\n", a, c, *((int*)&b) );
}
输出中有趣的部分是
a=2147483520 c=2147483520 b=0x4effffff
a=2147483521 c=2147483520 b=0x4effffff
...
a=2147483582 c=2147483520 b=0x4effffff
a=2147483583 c=2147483520 b=0x4effffff
a=2147483584 c=-2147483648 b=0x4f000000
a=2147483585 c=-2147483648 b=0x4f000000
...
a=2147483645 c=-2147483648 b=0x4f000000
a=2147483646 c=-2147483648 b=0x4f000000
请注意,从2147483584到2147483647的所有32位值将会被舍入到2147483648的值。最大的向下舍入的值是2147483583,这与32位系统上的
(INT_MAX - 64)
相同。
因此,有人可能得出结论,低于
(INT_MAX - 64)
的数字将安全地从转换为,并再次转换回。但这仅适用于
int
大小为32位,并且按IEEE-754进行编码的系统。
b
是不正确的。如果您仔细查看,您会发现它实际上是在第一次转换后的INT_MAX+1
。在您的平台上,INT_MAX
为2147483647,而不是2147483648。也就是说,第一次转换是引入结果增量的地方。在线查看 - WhozCraig