использование bitset с плавающими типами - PullRequest
3 голосов
/ 23 сентября 2011

Можно ли иметь битовый контейнер с плавающими типами данных? Пример:

bitset<sizeof(float)*sizeof(char)> second(5.5f);
cout << second.to_string() << endl;

Это не работает правильно. то, что я пытаюсь сделать, это получить представление битов.

Ответы [ 2 ]

7 голосов
/ 23 сентября 2011

bitset принимает только unsigned long в качестве аргумента конструктора.В вашем примере float преобразуется в unsigned long и затем используется в качестве аргумента.

Чтобы получить то, что вы хотите, используйте что-то вроде:

float f = 5.5f;
std::bitset<sizeof(float)*CHAR_BIT> foo(*reinterpret_cast<unsigned long*>(&f));

Это переосмысливает«память», в которой находится число с плавающей запятой, содержит unsigned long и, таким образом, «обманывает» конструктор.

2 голосов
/ 19 января 2018

Чтобы построить bitset из float четко определенным образом, вы должны:

  1. убедитесь, что ваши типы имеют совместимые размеры;
  2. скопировать представление вашего float в совместимое целое число;
  3. построить 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 демо )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...