浮点逆二进制表示

Floating point inverse binary representation

我对以下代码感到困惑:

int main()
{
    std::cout << std::bitset<32>(10.0f) << std::endl;
    std::cout << std::bitset<32>(-10.0f) << std::endl;

    float x = 10.0f;
    std::bitset<32> bsx(x);
    float y = -10.0f;
    std::bitset<32> bsy(y);
    std::cout << bsx << std::endl;
    std::cout << bsy << std::endl;
}

第二个只是(是的,它只是一个被截断的第一个):

int main()
{
    std::cout << std::bitset<32>(10.0f) << std::endl;
    std::cout << std::bitset<32>(-10.0f) << std::endl;
}

我得到以下输出: 第一个:

00000000000000000000000000001010
00000000000000000000000000000000
00000000000000000000000000001010
11111111111111111111111111110110

第二个:

00000000000000000000000000001010
00000000000000010010000001101000

系统是 macOS Sierra (10.12.3) 上的 Clang 4.0.0,据我所知这里的浮点数是 32 位。

(用 g++ -pedantic -std=c++14 编译。)

我唯一知道的浮点数是 IEEE-754,它规定应该有一个单独的符号位。第一个程序的最后输出似乎使用了补码...

而其他的完全令人困惑..所有零和有点随机的输出,即使使用相同的代码,也只是被截断了..

我误会了什么?我在代码中的某处出现未定义的行为吗?不懂语法?或者由于某种原因浮点数不能表示为位集?

此代码不显示浮点数的二进制表示,不。因为没有std::bitset constructors取浮点数。

它是这样工作的:

#include <bitset>
#include <iostream>
inline unsigned U(float f) { return (unsigned&) f; }

int main()
{
    std::cout << std::bitset<32>(U(10.0f)) << std::endl;
    std::cout << std::bitset<32>(U(-10.0f)) << std::endl;
    return 0;
}

我添加了另一种格式的显式重新读取值。 输出是

01000001001000000000000000000000
11000001001000000000000000000000

(当然,对于平台特定细节的传统免责声明应放在此处。)

更新:内存别名存在问题,导致转换器可以按以下方式更好地编写(至少对于现代 GCC 和 Clang):

inline unsigned U(float f) {
    unsigned R;
    memcpy(&R, &f, sizeof(R));
    return R;
}

现代编译器将此 memcpy() 视为 "bitcast" 运算符,并在内部将其转换为一种适当的寄存器移动。否则,您可能会遇到一些奇怪的别名问题。 但是,这种方法对于 ICC 来说仍然更糟,它更喜欢不同类型成员的联合:

inline unsigned U(float f) {
    union {
        unsigned u;
        float f;
    } t;
    t.f = f;
    return t.u;
}

对于不同的语言和版本,哪种类型的 bitcasting 更好,众说纷纭,在此不一一赘述。