打印浮点数的位数

San*_*Kim 0 c++ floating-point bitset type-punning

我知道。我知道。这个问题之前已经回答过,但我有一个稍微不同且更具体的问题。

正如标题所示,我的目标是浮动序列cout32 bits

前面的问题提供的解决方案是使用联合。

union ufloat{
   float f;
   uint32_t u;
};
Run Code Online (Sandbox Code Playgroud)

这一切都很好。我已经成功地打印了浮点数的位。

union ufloat uf;
uf.f = numeric_limits<float>::max();
cout << bitset<32>(uf.f) << "\n"; // This give me 0x00000000, which is wrong.
cout << bitset<32>(uf.u) << "\n"; // This give me the correct bit sequence.

Run Code Online (Sandbox Code Playgroud)

我的问题是为什么 dobitset<32>(uf.f)不起作用,但 bitset<32>(uf.u) 起作用?

这个问题的绿色勾号答案 获取了 C 中浮点数的位表示说了一些关于“类型双关”的内容,我认为它与此有关。但我不确定具体如何。

有人可以澄清一下吗?谢谢

Nel*_*eal 6

您正在调用的构造函数std::bitset是:
constexpr bitset( unsigned long long val ) noexcept;

当您这样做时bitset<32>(uf.f),您正在将 a 转换float为一个unsigned long long值。对于numeric_limits<float>::max(),这是未定义的行为,因为它超出了目标类型的范围,并且在您的情况下它恰好产生零。

当您这样做时bitset<32>(uf.u),您再次依赖于未定义的行为,在这种情况下,它恰好执行您想要的操作:将uint32_t包含 a 的位的a 转换floatunsigned long long值。

在 C++ 中,您应该使用 memcpy:

uint32_t u;
std::memcpy(&u, &uf.f, sizeof(u));
std::cout << std::bitset<32>(u) << "\n";
Run Code Online (Sandbox Code Playgroud)