我正在尝试将整数转换为像这样的浮点数(简化):
int64_t x = -((int64_t)1 << 63);
float y = x;
在64位Windows 7上使用MSVC 2013,这很好用,但在Ubuntu 14.04 64位上使用gcc 4.8我得到x的正值。我禁用了所有优化并查看了gdb中的变量。我甚至尝试直接用gdb进行评估,以找出问题的原因:
(gdb) print (float)(-((int64_t)1 << 63))
$33 = 9,22337204e+18
(gdb) print (float)(-9223372036854775808)
$39 = 9,22337204e+18
可以看出,即使添加显式强制转换也不能解决问题。我有点困惑,因为float
应该能够容纳更大的数字(就绝对值而言)。如果重要,请sizeof(float) == 4
和sizeof(size_t) == 8
。似乎值-2 ^ 63是一个神奇的限制,因为-2 ^ 63 + 1转换得非常好:
(gdb) print (float)(-((int64_t)1 << 63) + 1)
$44 = -9,22337149e+18
在转换值<= - 2 ^ 63时,符号丢失的原因是什么?值-2 ^ 63可以用int64_t和float表示;它可以在上述其他平台上运行。
答案 0 :(得分:5)
指令(int64_t)1 << 63
正在将1
转换为符号位,因此是未定义的行为。
即使转换成功并给0x8000000000000000
这是可以支持的最小(和负)值,那么用
-((int64_t)1 << 63)
将值放在正符号64位int
的范围之外。
答案 1 :(得分:2)
要避免未定义的行为,请使用the ldexp
standard function:- ldexp(1.0, 63)
乘以2的幂。