преобразовать двойное число в (IEEE 754) 64-битное двоичное представление строки в c ++ - PullRequest
3 голосов
/ 24 декабря 2011

У меня есть двойное число, я хочу представить его в 64-битной двоичной строке IEEE 754.В настоящее время я использую код, подобный следующему:

double noToConvert;
unsigned long* valueRef = reinterpret_cast<unsigned long*>(&noToConvert);

bitset<64> lessSignificative(*valueRef);
bitset<64> mostSignificative(*(++valueRef));

mostSignificative <<= 32;
mostSignificative |= lessSignificative;

RowVectorXd binArray = RowVectorXd::Zero(mostSignificative.size());
for(unsigned int i = 0; i <mostSignificative.size();i++)
{
    (mostSignificative[i] == 0) ? (binArray(i) = 0) : (binArray(i) = 1);
} 

Приведенный выше код работает без проблем.Но если вы видите, я использую reinterpret_cast и использую unsigned long.Таким образом, этот код очень зависит от компилятора.Может ли кто-нибудь показать мне, как написать код, который не зависит от платформы и без использования каких-либо библиотек.Я в порядке, если мы используем стандартные библиотеки и даже набор битов, но я не хочу использовать какой-либо машинно-зависимый код или компилятор.

Заранее спасибо.

Ответы [ 4 ]

5 голосов
/ 24 декабря 2011

Если вы хотите предположить, что double - это двойной тип IEEE-754:

#include <cstdint>
#include <cstring>

uint64_t getRepresentation(const double number) {
    uint64_t representation;
    memcpy(&representation, &number, sizeof representation);
}

Если вы даже не хотите делать такое предположение:

#include <cstring>

char *getRepresentation(const double number) {
    char *representation = new char[sizeof number];
    memcpy(representation, &number, sizeof number);
    return representation;
}
2 голосов
/ 24 декабря 2011

Почему бы не использовать союз?

bitset<64> binarize(unsigned long* input){
    union binarizeUnion   
    {
        unsigned long* intVal;
        bitset<64> bits;
    } binTransfer;
    binTransfer.intVal=input;
    return (binTransfer.bits);
}
1 голос
/ 24 декабря 2011

Функция print_raw_double_binary () в моей статье Отображение необработанных полей числа с плавающей точкой должна быть близка к той, что вы хотите. Возможно, вы захотите заменить приведение типа double к int на объединение, так как первое нарушает «строгий псевдоним» (хотя даже использование объединения для доступа к чему-то другому, отличному от того, что хранится, технически незаконно).

1 голос
/ 24 декабря 2011

Самый простой способ получить это - memcpy двойное в массив char:

char double_as_char[sizeof(double)];
memcpy(double_as_char, &noToConvert, sizeof(double_as_char));

, а затем извлечь биты из double_as_char. C и C ++ определяют это в стандарте как легальное.

Теперь, если вы действительно хотите извлечь различные компоненты double, вы можете использовать следующее:

sign= noToConvert<=-0.0f;
int exponent;
double normalized_mantissa= frexp(noToConvert, &exponent);
unsigned long long mantissa= normalized_mantissa * (1ull << 53);

Поскольку значение, возвращаемое frexp, находится в [0.5, 1), вам необходимо сдвинуть его на один дополнительный бит, чтобы получить все биты в мантиссе в виде целого числа. Затем вам просто нужно отобразить это в двоичном представлении, которое вы хотите, хотя вы должны будете скорректировать показатель степени, чтобы включить также неявное смещение.

...