如何在双变量中检查 inf(和 | 或)NaN
Posted
技术标签:
【中文标题】如何在双变量中检查 inf(和 | 或)NaN【英文标题】:How to check for inf (and | or) NaN in a double variable 【发布时间】:2010-11-04 09:35:39 【问题描述】:考虑以下代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
template<class T>
bool IsNaN(T t)
return t != t;
int main(int argc, char**argv)
double d1, d2;
sscanf(argv[1], "%f", &d1);
sscanf(argv[2], "%f", &d2);
double dRes = d1/d2;
cout << "dRes = " << dRes << "\n";
if(IsNaN(dRes))
cout << "Is NaN\n";
else
cout << "Not NaN\n";
几个问题:
-
当我将 0 和 0 作为参数传递时,它会输出
dRes = inf
。但我期待dRes = NaN
或类似的东西。
NaN 可以用双变量表示吗?就此而言,任何变量?
当我将 d1,d2,dRes 的数据类型更改为 int 并传递 0 和 0 时,我得到了一个Floating exception
。有什么区别?
如何检查变量的值是否等于inf
?
【问题讨论】:
【参考方案1】:使用scanf()
时,double
应使用%lf
而不是%f
读取。 %f
会将输入转换为 32 位 float
,因此变量的前 32 位将填充一些无效数据,而后 32 位将作为垃圾保留。
是的。 #include <limits>
,then std::numeric_limits<double>::quiet_NaN()
。一些编译器(例如 gcc)也提供了NAN
macro in <cmath>
。
整数类型没有 NaN 或无穷大。整数除以零会导致an exception (SIGFPE)。
#include <cmath>
,然后是std::isinf(x)
。使用 std::isfinite(x)
确保 x
不是 NaN 或 Infinity。
【讨论】:
整数除法和浮点除法的行为不同,因为整数除法是在硬件中完成的,而浮点除法不是?还是别的什么? @nakiya:不,浮点除法也是在硬件中完成的。不同之处在于无穷大不能用int
表示。
在此基础上,有没有办法从整数除以 0 中恢复? (除了预先检查值 - 我不能这样做,因为我无法控制该代码)。
@nakiya:你需要捕获 SIGFPE 信号,这实现起来相当复杂。
:(。是这样的。我们有一个脚本语言,支持基本的算术运算。唯一的问题是,它不检查除数是否为0。不能触摸库代码atm。输入系统也是人为设计的,因此我们无法轻松检查是否将 0 值作为除数传递。对于浮点值,如您所说,这是可以的。但是,整数有问题。【参考方案2】:
函数fpclassify
可以让您检查所有特殊情况的浮点值。
自 C99 以来,它在 <math.h>
中作为宏,在 <cmath>
中作为函数族,对于 float
、double
和 long double
,在 C++ 之后的重载名称 std::fpclassify
下11.
cppreference 有a nice example
【讨论】:
【参考方案3】:就那样做吧:
if (dRes == +1.0/0.0 || dRes == -1.0/0.0) ... //+INF, -INF
if (dRes == +0.0/0.0 ) ... //+NaN; i.e. pow(2.0 ,16384.0)
【讨论】:
如果dRes
是一个NaN,那么即使dRes == dRes
也是假的。这一事实创造了一种检查 NaN 的新方法,但这也意味着您的检查完全被破坏了。以上是关于如何在双变量中检查 inf(和 | 或)NaN的主要内容,如果未能解决你的问题,请参考以下文章