浮点逆二进制表示

Floating point inverse binary representation

本文关键字:表示 二进制      更新时间:2023-10-16

我对以下代码感到困惑:

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构造函数。

它的工作方式是这样的:

#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(( 视为"位播"运算符,并在内部将其转换为适当的寄存器移动。没有这个,您可能会遇到一些奇怪的混叠问题。但是,这种方法对于ICC来说仍然更糟,ICC更喜欢不同类型成员的联合:

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

关于哪种风格的位投更适合不同的语言和版本,存在相互矛盾的意见,我不会在这里深入探讨。