【问题标题】:Convert large integer to float将大整数转换为浮点数
【发布时间】:2015-05-06 14:09:39
【问题描述】:

我正在尝试将整数转换为这样的浮点数(简化):

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) == 4sizeof(size_t) == 8 以防万一。似乎值 -2^63 是一些神奇的限制,因为 -2^63+1 转换得非常好:

(gdb) print (float)(-((int64_t)1 << 63) + 1)
$44 = -9,22337149e+18

【问题讨论】:

  • (int64_t)1 &lt;&lt; 631 移入符号位,因此是未定义行为。
  • @WeatherVane:啊,感谢您指出这一点。它现在适用于(gdb) print (float)(-(int64_t)((uint64_t)1 &lt;&lt; 63)) $48 = -9,22337204e+18
  • 记住float只有一个24位尾数!
  • 只需使用INT64_MIN 并避免任何位移问题。
  • 如果可能,在否定之前进行强制转换。 2^63 和 -(2^63) 都可以用浮点数表示。

标签: c floating-point integer type-conversion


【解决方案1】:

指令(int64_t)1 &lt;&lt; 631 移入符号位,因此是未定义行为。

即使转移成功并给出了0x8000000000000000,这是可以支持的最小(和负)值,所以然后用否定该值

-((int64_t)1 << 63)

将值置于正符号 64 位 int 的范围之外。

【讨论】:

  • ... 这又是未定义的行为。所以每个编译器都是绝对正确的。
【解决方案2】:

为避免未定义的行为,请使用 the ldexp standard function 乘以 2 的幂:- ldexp(1.0, 63)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多