从int转到float并返回时,符号会发生变化

时间:2013-12-08 12:34:33

标签: c++ floating-point type-conversion ieee-754 twos-complement

考虑以下代码,这是我实际问题的SSCCE

#include <iostream>

int roundtrip(int x)
{
    return int(float(x));
}

int main()
{
    int a = 2147483583;
    int b = 2147483584;
    std::cout << a << " -> " << roundtrip(a) << '\n';
    std::cout << b << " -> " << roundtrip(b) << '\n';
}

我的电脑(Xubuntu 12.04.3 LTS)上的输出是:

2147483583 -> 2147483520
2147483584 -> -2147483648

请注意在往返后正数b如何结束为负数。这种行为是否明确规定?我原本期望int-to-float round-tripping至少能正确保存符号......

嗯,on ideone,输出不同:

2147483583 -> 2147483520
2147483584 -> 2147483647

g ++团队是否在此期间修复了错误,或两个输出都完全有效?

1 个答案:

答案 0 :(得分:69)

由于从浮点到整数的转换溢出,您的程序正在调用未定义的行为。你看到的只是x86处理器上常见的症状。

最接近float的{​​{1}}值恰好是2 31 (从整数到浮点的转换通常是舍入到最近的,可以是up,并且是在这种情况下。具体来说,从整数转换为浮点时的行为是实现定义的,大多数实现将舍入定义为“根据FPU舍入模式”,FPU的默认舍入模式是舍入到最近的)。

然后,在从表示2 31 的float转换为2147483584时,发生溢出。这种溢出是未定义的行为。一些处理器引发异常,其他处理器饱和。通常由编译器生成的IA-32指令int在溢出的情况下总是返回cvttsd2si,无论浮动是正还是负。

即使您知道自己的目标是英特尔处理器,也不应该依赖此行为:当定位x86-64时,编译器可以发出,从浮点数转换为整数sequences of instructions that take advantage of the undefined behavior to return results other than what you might otherwise expect for the destination integer type