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