[英]Why does std::bitset only support integral data types? Why is float not supported?
在尝试生成浮点的位模式时,如下所示:
std::cout << std::bitset<32>(32.5) << std::endl;
编译器生成此警告:
warning: implicit conversion from 'double' to 'unsigned long long' changes value
from 32.5 to 32 [-Wliteral-conversion]
std::cout << std::bitset<32>(32.5) << std::endl;
输出忽略警告:):
00000000000000000000000000100000
为什么不能bitset检测浮点数并正确输出位序列,当转换为char *并且行走内存确实显示正确的序列? 这是有效的,但机器依赖于字节顺序,并且几乎不可读:
template <typename T>
void printMemory(const T& data) {
const char* begin = reinterpret_cast<const char*>(&data);
const char* end = begin + sizeof(data);
while(begin != end)
std::cout << std::bitset<CHAR_BIT>(*begin++) << " ";
std::cout << std::endl;
}
输出:
00000000 00000000 00000010 01000010
有没有理由不支持花车? 浮筒有替代品吗?
如果你提供浮动,你会期望在你的bitset中出现什么? 大概是以big-endian格式表示IEEE-7545 binary32浮点数? 那些不代表他们的float
的平台甚至可以远远地类似于那个? 实施是否应该向后弯曲(可能是有损)将提供的浮动转换为您想要的?
它没有的原因是浮点数没有标准的定义格式。 它们甚至不必是32位。 他们通常只在大多数平台上。
C ++和C将在非常小的和/或奇怪的平台上运行。 标准不能指望“通常情况”是什么。 有8/16位6502系统的C / C ++编译器,对于原生浮点格式而言,遗憾的是(我认为)是一个使用压缩BCD编码的6字节实体。
这与signed
整数也不受支持的原因相同。 两个补充不是普遍的,几乎是普遍的。 :-)
关于浮点格式没有标准化,字节序等等的所有常见警告
这里的代码可能会起作用,至少在x86硬件上是这样。
#include <bitset>
#include <iostream>
#include <type_traits>
#include <cstring>
constexpr std::uint32_t float_to_bits(float in)
{
std::uint32_t result = 0;
static_assert(sizeof(float) == sizeof(result), "float is not 32 bits");
constexpr auto size = sizeof(float);
std::uint8_t buffer[size] = {};
// note - memcpy through a byte buffer to satisfy the
// strict aliasing rule.
// note that this has no detrimental effect on performance
// since memcpy is 'magic'
std::memcpy(buffer, std::addressof(in), size);
std::memcpy(std::addressof(result), buffer, size);
return result;
}
constexpr std::uint64_t float_to_bits(double in)
{
std::uint64_t result = 0;
static_assert(sizeof(double) == sizeof(result), "double is not 64 bits");
constexpr auto size = sizeof(double);
std::uint8_t buffer[size] = {};
std::memcpy(buffer, std::addressof(in), size);
std::memcpy(std::addressof(result), buffer, size);
return result;
}
int main()
{
std::cout << std::bitset<32>(float_to_bits(float(32.5))) << std::endl;
std::cout << std::bitset<64>(float_to_bits(32.5)) << std::endl;
}
示例输出:
01000010000000100000000000000000
0100000001000000010000000000000000000000000000000000000000000000
#include <iostream>
#include <bitset>
#include <climits>
#include <iomanip>
using namespace std;
template<class T>
auto toBitset(T x) -> bitset<sizeof(T) * CHAR_BIT>
{
return bitset<sizeof(T) * CHAR_BIT>{ *reinterpret_cast<unsigned long long int *>(&x) };
}
int main()
{
double x;
while (cin >> x) {
cout << setw(14) << x << " " << toBitset(x) << endl;
}
return 0;
}
https://wandbox.org/permlink/tCz5WwHqu2X4CV1E
遗憾的是,如果参数类型大于unsigned long long
大小,则会失败,例如,对于long double
,它将失败。 这是bitset
构造函数的限制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.