преобразование double в int64_t с++

int64_t a = *(int64_t *)&x;

почему после данной строки а становится равным -4661117527937406468 при double х=-0.001, понятно, что мы начинаем работать со значением переменной x в типе данных int64_t, но что происходит именно при конвертировании, получается ведь -4661117527937406468 в бинарном представлении равно -0.001?


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Число двойной точности: такой формат у double, если значение конечное и не равно нулю. Старший бит - знак. Дальше одиннадцать бит - экспонента (e). Остальные биты - мантисса (m).

Чтобы собрать число из кусков, надо посчитать (1 + m/252)×2e-1023. Потом ставите знак и готово:

#include <cstring>
#include <iostream>

int main() {
    double d;
    std::cin >> d;

    int64_t n;
    static_assert(sizeof n == sizeof d);
    // это правильный способ приводить значения
    // компилятор превращает это в одну инструкцию копирования,
    // никаких вызовов функций
    std::memcpy(&n, &d, sizeof d);

    std::cout << n << '\n';

    auto sign = (n >> 63) & 1;
    auto exponent = (n >> 52) & ((1LL << 11) - 1);
    auto mantissa = n & ((1LL << 52) - 1);

    std::cout << sign << ' ' << exponent << ' ' << mantissa << '\n';

    double d2 = 1. + double(mantissa) / double(1LL << 52);
    for (int i = 1023; i < exponent; ++i) {
        d2 *= 2;
    }
    for (int i = 1023; i > exponent; --i) {
        d2 /= 2;
    }
    if (sign == 1) {
        d2 = -d2;
    }
    std::cout << d2 << '\n';
}
$ g++ format.cpp 

$ echo -0.001 | ./a.out
-4661117527937406468
1 1013 108086391056892
-0.001
→ Ссылка