gpt4 book ai didi

c++ - 为什么打印这个值虽然是 NaN?

转载 作者:可可西里 更新时间:2023-11-01 15:27:47 26 4
gpt4 key购买 nike

以下代码假定我们在 x86 兼容系统上并且 long double映射到 x87 FPU 的 80 位格式。

#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(value1): true

isnan(value2): false

isnan(value3): false

value1: 3.3614005946481929011e-4764

value2: 9.7056260598879139386e-4764

value3: 6.3442254652397210376e-4764

在这里value1被 387 及更高分类为“不受支持”,因为它具有非零指数且不是全一指数——它实际上是一个“不正常”。和 isnan它按预期工作:该值确实不是数字(尽管不完全是 NaN)。第二个值,value2 , 设置了那个整数位,并且也按预期工作:它不是 NaN。第三个是缺失整数位的值。

但不知何故这两个数字 value1value2显示为已打印,并且值因缺少整数位而完全不同!这是为什么?我尝试过的所有其他方法,例如 printfto_string只给 0.00000 .

更奇怪的是,如果我用 value1 做任何算术运算,在随后的打印中我确实得到了 nan .考虑到这一点,如何operator<<(long double)甚至设法打印除了nan以外的任何东西?它是否显式设置整数位,或者它可能解析数字而不是对其进行任何 FPU 运算? (假设 Linux 32 位上的 g++4.8)。

最佳答案

All other methods I tried, like printf and to_string give just 0.00000.

什么 operator<<(long double)实际上是使用 num_put<>来自 locale 的类(class)执行数字格式化的库,它又使用 printf 之一-family 函数(参见 C++ 标准的第 27.7.3.6 和 22.4.2.2 节)。

根据设置,printf 转换说明符用于 long double通过 locale可能是以下任何一个:%Lf , %Le , %LE , %La , %LA , %Lg%LG .

在你(和我)的情况下,它似乎是 %Lg :

printf("value1: %.20Lf\n", value1);
printf("value1: %.20Le\n", value1);
printf("value1: %.20La\n", value1);
printf("value1: %.20Lg\n", value1);
std::cout << "value1: " << std::setprecision(20) << value1 << "\n";

value1: 0.00000000000000000000

value1: 3.36140059464819290106e-4764

value1: 0x4.3d1ac8f246f235200000p-15826

value1: 3.3614005946481929011e-4764

value1: 3.3614005946481929011e-4764


Taking this into account, how does operator<<(long double) even manage to actually print anything but nan? Does it explicitly set the integer bit, or maybe it parses the number instead of doing any FPU arithmetic on it?

它打印未规范化的值。

printf() 使用的从二进制到十进制浮点表示的转换可以在没有任何 FPU 算法的情况下执行。您可以在 stdio-common/printf_fp.c 中找到 glibc 实现。源文件。

关于c++ - 为什么打印这个值虽然是 NaN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31641329/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com