将 INT_MAX 转换为浮点数,然后再转换回整数. [英] Convert INT_MAX to float and then back to integer.

查看:40
本文介绍了将 INT_MAX 转换为浮点数,然后再转换回整数.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C 编程中,我发现了一个奇怪的问题,这与我的直觉相反.当我将 integer 声明为 INT_MAX(2147483647,在limits.h 中定义)并将其隐式转换为float 值,它工作正常,即浮点值与最大整数相同.然后,我将浮点数转换回整数,有趣的事情发生了.新的 integer 成为最小整数 (-2147483648).
源代码如下:

In C programming, I find a weird problem, which counters my intuition. When I declare a integer as the INT_MAX (2147483647, defined in the limits.h) and implicitly convert it to a float value, it works fine, i.e., the float value is same with the maximum integer. And then, I convert the float back to an integer, something interesting happens. The new integer becomes the minimum integer (-2147483648).
The source codes look as below:

int a = INT_MAX;
float b = a; // b is correct
int a_new = b; // a_new becomes INT_MIN

我不确定当浮点数 b 转换为整数 a_new 时会发生什么.那么,有没有什么合理的解决方案可以找到integerfloat类型之间可以来回切换的最大值?

I am not sure what happens when the float number b is converted to the integer a_new. So, is there any reasonable solution to find the maximum value which can be switched forth and back between integer and float type?

PS:INT_MAX 的值 - 100 工作正常,但这只是一个任意的解决方法.

PS: The value of INT_MAX - 100 works fine, but this is just an arbitrary workaround.

推荐答案

此答案假定 float 是编码为 32 位的 IEEE-754 单精度浮点数,并且 int 是 32 位.有关 IEEE-754 的更多信息,请参阅这篇维基百科文章.

This answer assumes that float is an IEEE-754 single precision float encoded as 32-bits, and that an int is 32-bits. See this Wikipedia article for more information about IEEE-754.

浮点数只有 24 位精度,而 int 则为 32 位.因此,从 0 到 16777215 的 int 值具有作为浮点数的精确表示,但大于 16777215 的数字不一定具有作为浮点数的精确表示.以下代码演示了这一事实(在使用 IEEE-754 的系统上).

Floating point numbers only have 24-bits of precision, compared with 32-bits for an int. Therefore int values from 0 to 16777215 have an exact representation as floating point numbers, but numbers greater than 16777215 do not necessarily have exact representations as floats. The following code demonstrates this fact (on systems that use 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 的确切值.

Of interest here is that the float value 0x4b800002 is used to represent the three int values 16777219, 16777220, and 16777221, and thus converting 16777219 to a float and back to an int does not preserve the exact value of the int.

最接近INT_MAX的两个浮点值是2147483520和2147483648,可以用这段代码演示

The two floating point values that are closest to INT_MAX are 2147483520 and 2147483648, which can be demonstrated with this code

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 位 int 值将向上舍入为 float 值 2147483648.最大的 int向下舍入的值为 2147483583,与 32 位系统上的 (INT_MAX - 64) 相同.

Note that all 32-bit int values from 2147483584 to 2147483647 will be rounded up to a float value of 2147483648. The largest int value that will round down is 2147483583, which the same as (INT_MAX - 64) on a 32-bit system.

因此,人们可能会得出结论,(INT_MAX - 64) 以下的数字将安全地从 int 转换为 float 并返回到 int.但这仅适用于 int 的大小为 32 位且 float 根据 IEEE-754 编码的系统.

One might conclude therefore that numbers below (INT_MAX - 64) will safely convert from int to float and back to int. But that is only true on systems where the size of an int is 32-bits, and a float is encoded per IEEE-754.

这篇关于将 INT_MAX 转换为浮点数,然后再转换回整数.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆