Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将INT_MAX转换为float,然后再转换回integer。_C_Type Conversion_Integer Overflow - Fatal编程技术网

C 将INT_MAX转换为float,然后再转换回integer。

C 将INT_MAX转换为float,然后再转换回integer。,c,type-conversion,integer-overflow,C,Type Conversion,Integer Overflow,在C编程中,我发现了一个奇怪的问题,这与我的直觉相反。当我将一个整数声明为INT_MAX(2147483647,在limits.h中定义)并隐式将其转换为浮点值时,它工作正常,即浮点值与最大整数相同。然后,我把浮点数转换成一个整数,有趣的事情发生了。新的整数成为最小整数(-2147483648)。 源代码如下所示: int a = INT_MAX; float b = a; // b is correct int a_new = b; // a_new becomes INT_MIN 我不确定

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

int a = INT_MAX;
float b = a; // b is correct
int a_new = b; // a_new becomes INT_MIN
我不确定当浮点数
b
转换为整数
a\u new
时会发生什么。那么,有没有合理的解决方案来找到可以在
integer
float
类型之间来回切换的最大值


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

该答案假设
float
是编码为32位的IEEE-754单精度浮点,而
int
是32位。有关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) );
}

浮点数的精度只有24位,而整数的精度是32位。因此,0到16777215之间的整数值具有浮点数的精确表示形式,但大于16777215的数字不一定具有浮点数的精确表示形式。以下代码演示了这一事实(在使用IEEE-754的系统上)

这里值得注意的是,
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) );
}
请注意,从2147483584到2147483647的所有32位
int
值将向上舍入为
float
值2147483648。将四舍五入的最大
int
值为2147483583,与32位系统上的
(int\u MAX-64)
相同


因此,人们可能会得出结论,低于
(INT_MAX-64)
的数字将安全地从
INT
转换为
float
并返回到
INT
。但这仅适用于
int
大小为32位的系统,而
float
是按照IEEE-754进行编码的。

浮点的精度有限,因此我认为这种转换并不奇怪。与您的评论相反,
b
是不正确的。如果你仔细观察它,我想你会发现它在第一次转换后实际上是
INT\u MAX+1
<您平台上的代码>INT_MAX
是2147483647,而不是2147483648。即,第一次转换是首先引入结果增量的地方。4字节浮点使用23位存储尾数,9位存储符号和指数。这意味着存储最大的32位整数不可能完全准确。看起来问题并不是在所有平台上都会发生:请看@AurélienGasser,这是一个谬误。我确信编译器在默认情况下会进行优化。禁用优化,然后查看结果。所讨论的数字不能精确地表示为浮点,因此无法将其取回。
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=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