В следующем коде предполагается, что мы находимся в x86-совместимой системе и что long double
отображается в 80-битный формат x87 FPU.
#include <cmath>
#include <array>
#include <cstring>
#include <iomanip>
#include <iostream>
int main()
{
std::array<uint8_t,10> data1{0x52,0x23,0x6f,0x24,0x8f,0xac,0xd1,0x43,0x30,0x02};
std::array<uint8_t,10> data2{0x52,0x23,0x6f,0x24,0x8f,0xac,0xd1,0xc3,0x30,0x02};
std::array<uint8_t,10> data3{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x30,0x02};
long double value1, value2, value3;
static_assert(sizeof value1 >= 10,"Expected float80");
std::memcpy(&value1, data1.data(),sizeof value1);
std::memcpy(&value2, data2.data(),sizeof value2);
std::memcpy(&value3, data3.data(),sizeof value3);
std::cout << "isnan(value1): " << std::boolalpha << std::isnan(value1) << "\n";
std::cout << "isnan(value2): " << std::boolalpha << std::isnan(value2) << "\n";
std::cout << "isnan(value3): " << std::boolalpha << std::isnan(value3) << "\n";
std::cout << "value1: " << std::setprecision(20) << value1 << "\n";
std::cout << "value2: " << std::setprecision(20) << value2 << "\n";
std::cout << "value3: " << std::setprecision(20) << value3 << "\n";
}
Вывод:
isnan (значение1): true
isnan (значение2): false
isnan (значение3): false
значение1: 3.3614005946481929011e-4764
значение2: 9.7056260598879139386e-4764
значение3: 6.3442254652397210376e-4764
Здесь value1
классифицируется как "неподдерживаемый" на 387 и выше, потому что он имеет ненулевой и не все-показательный показатель - он на самом деле "ненормальный". И isnan
работает так, как ожидалось, с ним: значение действительно не имеет никакого числа (хотя и не точно NaN). Второе значение value2
имеет этот битовый набор, а также работает как ожидалось: это не NaN. Третий - это значение отсутствующего целочисленного бита.
Но так или иначе отображаются как цифры value1
, так и value2
, и значения в точности отличаются от отсутствующего целочисленного бита! Почему это? Все другие методы, которые я пробовал, например printf
и to_string
, дают только 0.00000
.
Даже незнакомец, если я делаю арифметику с value1
, в последующих отпечатках я получаю nan
. Принимая это во внимание, как operator<<(long double)
удается даже напечатать что-либо, кроме nan
? Является ли это явным образом заданием целочисленного бита, или, может быть, он анализирует число вместо того, чтобы выполнять какую-либо арифметику FPU? (предполагая g++ 4.8 на Linux 32 бит).