Чтобы построить bitset
из float
четко определенным образом, вы должны:
- убедитесь, что ваши типы имеют совместимые размеры;
- скопировать представление вашего
float
в совместимое целое число;
- построить
bitset
из этого целого числа.
Вот минимальный пример:
#include <bitset>
#include <cstring>
float f = 1.618;
static_assert(sizeof(float) <= sizeof(long long unsigned int), "wrong sizes"); // 1.
long long unsigned int f_as_int = 0;
std::memcpy(&f_as_int, &f, sizeof(float)); // 2.
std::bitset<8*sizeof(float)> f_as_bitset{f_as_int}; // 3.
Но это не сработает должным образом для цели с прямым порядком байтов, чья long long unsigned int
больше float
, потому что конструктор набора битов всегда выбирает младшие значащие биты аргумента независимо от порядок байтов И это отстой.
Итак, если мы хотим быть завершенными, мы должны решить это. Для этого можно скопировать число с плавающей точкой в целое число того же размера (2.), затем cast (3.) в long long unsigned int
, что приведет к представлению , не зависящему от порядка байтов . Но да, решение, не зависящее от порядка байтов, утомительно :
#include <bitset>
#include <cstring>
#include <cstdint>
#include <iostream>
namespace details
{
template<unsigned nbits> struct uint {};
template<> struct uint<8> { using type = uint8_t; };
template<> struct uint<16> { using type = uint16_t; };
template<> struct uint<32> { using type = uint32_t; };
template<> struct uint<64> { using type = uint64_t; };
}
template<class T>
using unsigned_integer_of_same_size = typename details::uint<sizeof(T)*8>::type;
int main()
{
float f = -1./0.;
static_assert(sizeof(float) <= sizeof(long long unsigned int), "wrong sizes"); // 1.
unsigned_integer_of_same_size<float> f_as_uint = 0;
std::memcpy(&f_as_uint, &f, sizeof(float)); // 2.
std::bitset<8*sizeof(float)> f_as_bitset{f_as_uint}; // 3. && 4.
std::cout << f_as_bitset << "\n";
}
( live демо )