NaN传播通过"大多数" NaN - Wikipedia中描述的操作。
我想知道NaN不传播的操作。例如,我在C ++中进行编码,发现以下代码打印的是1
,而不是NaN。
const double result = std::pow(1, std::numeric_limits<double>::quiet_NaN());
std::cout << result << std::endl;
对于std::pow
函数,std::pow - cppreference.com中描述了此行为。
你可以分享其他任何例子吗?
答案 0 :(得分:6)
std::pow
在某种意义上并不是真正的运算符,因为a * b
中的乘法就像是一个操作。它是功能。函数可以有分支,可以随意处理NaN
。在某种意义上,另一个类似的std
函数是std::is_nan
。这也不会传播NaN
:它返回一个bool
,它可以隐式转换为数字类型:
std::is_nan(std::is_nan(a))
对于允许表达式编译的任何类型false
,是a
。其他示例包括std::fpclassify
和std::isfinite
。我特别喜欢std::fpclassify
作为示例,因为它具有int
返回类型,所以它实际上不仅仅是pow
的数字函数!
请注意,NaN
到bool
的隐式转换根据{{3}的接受答案定义为 false
true
这很重要。它允许!
,&&
和||
与NaN
一起使用。最后,表达式分隔符运算符 ,
也不会传播NaN
,并且忽略三元条件运算的未使用分支上的NaN
。
答案 1 :(得分:3)
我会尝试的另一种情况是pow(0, NaN)
。如果有pow(0,0) == 1
,那么应该期待
pow(0, NaN) == 1
这有一个理由,实际上它需要一致的行为。 即使没有IEEE标准规定基本功能相对于NaN的行为,也有一个非常基本的规则:
如果所有有限点数x
包括+ inf和-inf(但不包括NaN)我们有
f(const1, x) == const2
然后(并且只有那时)还必须返回非NaN结果
f(const1, NaN) == const2
这是因为NaN表示“未定义”或“来自-inf .. inf的任何其他数值”。为什么?考虑原型示例0/0。 如果有一个等式
b = a * x
并希望解决x
。显然,解决方案是
x = b/a
现在如果a == b == 0
那么原始方程有无限多个解,即所有有限数x
。这就是NaN意味着“未指定”和0/0 == NaN
的原因。现在,如果未指定的数字(即NaN)作为参数输入函数,则通常会导致“未指定”的答案。例外情况是输出不依赖于输入,在这种情况下,应该/不得返回NaN。
考虑
pow(1, a/b)
对于非零a
和b
,此表达式的计算结果始终为1,从数学角度来看这是有道理的,因为数学意义上的1^x
不依赖于{{1} }}。所以在数字上也会要求,x
或a = 0
(因而b = 0
)也会得到1。
所以,如果有人同意这个事实
x=NaN
然后还必须定义
pow(1,-inf) = pow(1,inf) = 1
表示一致的行为。这同样适用于pow(1,NaN) = 1
,但是对零度多项式的求值也应该在NaN输入上生成非NaN输出。
注意:此推理可应用于任何功能,包括内置运算符。
答案 2 :(得分:3)
这是一个证明NaN返回非NaN功能的例子。该列表在IEEE 754-2008中, 9.2.1特殊值(还有一些其他功能,但它们似乎没有在C ++中实现):
#include <cmath>
#include <limits>
#include <iostream>
int main()
{
const auto nan=std::numeric_limits<double>::quiet_NaN();
const auto inf=std::numeric_limits<double>::infinity();
std::cout << std::hypot(nan,inf) << '\n';
std::cout << std::hypot(inf,nan) << '\n';
std::cout << std::pow(nan, 0) << '\n';
std::cout << std::pow(1,nan) << '\n';
}
输出结果为:
inf
inf
1
1