如何打印NaN的有效负载
How to print payload of a NaN?
我们有像std::nanl
这样的特殊函数来生成带有有效负载的NaN。目前,我要做的是打印回来:
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdint>
int main()
{
const auto x=std::nanl("1311768467463790325");
std::uint64_t y;
std::memcpy(&y,&x,sizeof y);
std::cout << (y&~(3ull<<62)) << "n";
}
这取决于long double
的特定表示,即它是x87 FPU的80位类型。有没有任何标准的方法可以在不依赖于这些实施细节的情况下实现这一点?
C++从ISO C导入nan*
函数。ISO C在7.22.1.3中声明:
n字符序列的含义是实现定义的
带有注释
一种实现可以使用n-char序列来确定要在NaN的有效位中表示的额外信息。
没有获取存储信息的方法。
我在2023年偶然发现了这个。
情况没有太大改善
- C11支持
nan*()
功能(如果目标处理器支持QNaN),但是 - MSVC 2022实际上没有实现有效载荷编译
- 有效负载必须指定为字符串,并且
- 仍然没有获取数据的标准方法
- (C23提出了GNU扩展
getPayload()
,但它返回了另一个double
,这远没有整数那么有趣。)
然而
假设您有一个带有有效载荷数据的适当IEEE 754 QNaN,那么获得QNaN有效载荷一直是可能的。例如,它在执行Javascript和Lua等操作的系统上得到了很好的使用[需要引文]
根据维基百科,在讨论了一些恐龙之后:[链接]
因此,广泛使用的IEEE 754浮点标准没有指定字节序,这可能显得很奇怪[3]从理论上讲,这意味着即使是一台机器编写的标准IEEE浮点数据也可能无法被另一台机器读取。然而,在现代标准计算机(即,实现IEEE 754)上,可以有把握地假设浮点数的字节序与整数的字节序相同,无论数据类型如何,转换都很简单。然而,使用特殊浮点格式的小型嵌入式系统可能是另一回事
强调
因此,只要你没有在内部使用之外泄露抽象,或者使用专门的(或古老的)硬件,那么你就应该善于在QNaN中填充东西。
由于这个问题被标记为C++
,我们将不得不使用比C
中严格需要的代码稍微丑陋的代码,因为在C++中,带有并集的类型双关语(可能)是UB[更多链接]以下内容应该在C和C++中都能工作,并且无论哪种方式都能产生同样优化的代码。
达或回家
qnan.h
#ifndef QNAN_H
#define QNAN_H
// Copyright stackoverflow.com
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt )
#include <assert.h>
#include <math.h>
#include <stdint.h>
#ifndef NAN
#error "IEEE 754 Quiet NaN is required."
#endif
#ifndef UINT64_MAX
#error "uint64_t required."
#endif
static_assert( sizeof(double) == 8, "IEEE 754 64-bit double-precision is required" );
double qnan ( unsigned long long payload );
unsigned long long qnan_payload ( double qnan );
#endif
qnan.c
// Copyright stackoverflow.com
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt )
#include <string.h>
#include "qnan.h"
double
qnan( unsigned long long payload )
{
double qnan = NAN;
uint64_t n;
memcpy( &n, &qnan, 8 );
n |= payload & 0x7FFFFFFFFFFFFULL;
memcpy( &qnan, &n, 8 );
return qnan;
}
unsigned long long
qnan_payload( double qnan )
{
uint64_t n;
memcpy( &n, &qnan, 8 );
return n & 0x7FFFFFFFFFFFFULL;
}
这两个函数允许您访问作为无符号整数的所有51位有效负载数据。
然而,请注意,与奇怪的o getPayload()
函数不同,qnan_payload()
函数并不麻烦对您的输入选择进行事实核查——它假设您已经给了它一个实际的QNaN。
如果你不确定你有什么类型的double
,<math.h>
中的isnan()
函数可以很好地检查QNaNess。
类似的代码将允许您访问四字节float
或N字节long double
(这可能只是一个8字节double
,除非它不是,而且可能更难支持)。
- 欧拉项目#8答案是大以获得有效答案
- 调整大小后指向元素值的指针unordered_map有效?
- 为什么是0;C++中的有效语句
- 最高有效数字侧的第N位
- GCC对可能有效的代码抛出init list生存期警告
- 有效地使用std::unordered_map来插入或增加键的值
- c++中O(n^(1/3))中一个数的除数的有效计数
- 使用无符号字符数组有效存储内存
- 自定义先决条件对移动分配运算符有效吗
- g++的分段错误(在NaN上使用to_string两次时)
- 输出是NaN,如何
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 为什么这种直接初始化有效?(C++17)
- 递归函数有效,但无法记忆
- 为什么我在输出端得到 nan?
- 在C++中初始化向量映射的最有效方法
- 提升反序列化对象具有 nan 或 -nan 值
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 如何打印NaN的有效负载