LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

揭秘 C++ 中的 NaN:产生原因、特性详解及处理方法

freeflydom
2024年4月13日 10:25 本文热度 32

本文作者希望通过这篇文章,让开发者深入了解 C++ 中的 NaN 值及其有效处理方式。


原文链接:https://alexsyniakov.com/2024/03/20/understanding-nan-numbers-in-c-and-their-properties/

作者 | Alex Syniakov

翻译 | 郑丽媛


NaN,即“Not a Number”,表示在实数范围内无法表达的数值。它的特殊性质,使得在编程(尤其是在 C++ 中)中处理 NaN 值成为许多开发人员感兴趣的话题。为此,本文将深入探讨什么是 NaN 值、它们是如何产生的、它们的特性以及如何在 C++ 中有效地处理它们。



一、NaN 是如何产生的?

NaN 值可能由不产生确定或实数结果的操作而产生,常见例子包括:

零除以零;

无穷大除以无穷大;

零乘以无穷大;

带相反符号的无穷级数相加;

计算负数的平方根;

取负数的对数;

使用非数字操作数进行复杂的数学运算。

此外,在 C++ 中,还可以使用 std::nan(const char*) 或 std::numeric_limits<double>::quiet_NaN() 来明确地创建 NaN 值。

二、NaN 的特性

NaN 的一个显著特点是在比较时的行为。在全等运算中,NaN 与其他任何值相比,结果都是 false。示例如下:

double nanValue = 0.0 / 0.0;

bool alwaysFalse = nanValue == nanValue; // false

bool alwaysTrue = nanValue != nanValue; // true

要确定一个值是否为 NaN,可将该值与自身进行比较:

bool isNan = nanValue != nanValue;

此外,在 C++ 中,有一个内置函数 std::is_nan(从 C++11 开始)也可以让你检查一个数字是否为 NaN。

三、NaN 对数据结构的影响

因此,如果您在计算中得到了 NaN 作为结果,然后将此值用于关联容器中,例如:

std::set<double> test;

test.insert(NaNvalue);

test.insert(1.0); // 不会插入 test.insert(2.0); // 不会插入

此后,由于 NaN 不满足关联容器键的严格弱排序要求,无法向集合中插入任何值。

四、NaN 的标准和类型

IEEE 754 标准将 NaN 值分为“quiet NaNs”(qNaNs)和“signaling NaNs”(sNaNs)。Quiet NaNs 允许计算继续进行而不受干扰,在算术运算中悄无声息地传播。而 Signaling NaNs 则会触发异常,立即处理无效操作。尽管这两种 NaN 类型的区别很重要,但在 C++ 或 IEEE 754 标准库接口中并没有明确处理,更多地取决于底层硬件和编译器行为。

五、检查 NaN

各种数学库都提供了 NaN 检查函数,例如,glm 有一个函数,用于检查向量的各个分量是否为 NaN,并返回一个布尔向量:

glm::dvec3 NaNvector = someFunction();

bool isNaN = glm::all(glm::isnan(NaNvector));

一个更好的做法是,不仅检查一个数字是否为 NaN,还应该进行更全面的检查——判断数字是否有限。为此,std 提供了函数 std::isfinite(从 C++11 开始),在 glm 中也有类似的向量函数。

std::println("{}", std::isfinite(std::numeric_limits<double>::quiet_NaN()));

std::println("{}", std::isfinite(std::numeric_limits<double>::infinity()));

std::println("{}", std::isfinite(-std::numeric_limits<double>::infinity()));

std::println("{}", std::isfinite(0.0));

std::println("{}", std::isfinite(std::exp(1000)));

std::println("{}", std::isfinite(std::numeric_limits<double>::min()));

六、结论

在 C++ 中处理 NaN 值需要了解它们的生成、属性以及对数据结构的影响。通过利用内置函数并遵循最佳实践,开发人员可以有效管理 NaN 值,确保他们的软件可以优雅地处理边缘情况,并在整个计算过程中保持数值的完整性。


————————————————

 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/csdnnews/article/details/137580018



该文章在 2024/4/13 10:29:49 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved