按位C代码舍入问题

我必须遵循按位代码,它将浮点值(打包在int中)转换为int值。

问题:存在舍入问题,因此在输入为0x80000001的情况下失败。 我该如何处理?

这是代码:

if(x == 0) return x; unsigned int signBit = 0; unsigned int absX = (unsigned int)x; if (x < 0) { signBit = 0x80000000u; absX = (unsigned int)-x; } unsigned int exponent = 158; while ((absX & 0x80000000) == 0) { exponent--; absX <> 8; unsigned int result = signBit | (exponent << 23) | (mantissa & 0x7fffff); printf("\nfor x: %x, result: %x",x,result); return result; 

那是因为0x80000001的精度超过了float 。 读取链接的文章,浮点数的精度是24位,因此任何一对浮点数( x - y )小于两个>> 24的最高位都是无法检测到的。 gdb同意你的演员:

main.c中:

 #include  int main() { float x = 0x80000001; printf("%f\n",x); return 0; } 

GDB:

 Breakpoint 1, main () at test.c:4 4 float x = 0x80000001; (gdb) n 5 printf("%f\n",x); (gdb) px $1 = 2.14748365e+09 (gdb) p (int)x $2 = -2147483648 (gdb) p/x (int)x $3 = 0x80000000 (gdb) 

这种不精确的极限:

 (gdb) p 0x80000000 == (float)0x80000080 $21 = 1 (gdb) p 0x80000000 == (float)0x80000081 $20 = 0 

实际的按位表示:

 (gdb) p/x (int)(void*)(float)0x80000000 $27 = 0x4f000000 (gdb) p/x (int)(void*)(float)0x80000080 $28 = 0x4f000000 (gdb) p/x (int)(void*)(float)0x80000081 $29 = 0x4f000001 

double s确实有足够的精度来区分:

 (gdb) p 0x80000000 == (float)0x80000001 $1 = 1 (gdb) p 0x80000000 == (double)0x80000001 $2 = 0