NaN何时不在C++中传播?

Tom*_*ota 6 c++ nan

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中描述.

你能分享一下其他的例子吗?

Bat*_*eba 6

std::pow在某种意义上,乘法运算并不是真正的运算符a * b.这是一个功能.功能可以有分支,可以随心所欲地处理NaN.std在某种意义上,另一个类似的功能std::is_nan.这也不会传播NaN:它返回一个bool可隐式转换为数字类型的东西:

std::is_nan(std::is_nan(a))
Run Code Online (Sandbox Code Playgroud)

适用falsea允许表达式编译的任何类型.其他例子包括std::fpclassifystd::isfinite.我特别喜欢它std::fpclassify作为一个例子,因为它有一个int返回类型,所以它真的不是一个数字函数pow!

请注意,NaNto 的隐式转换bool定义为false true根据这个问题的接受答案,这很重要.它允许!,&&||使用NaN.最后,表达式分隔符运算符 ,也不会传播NaN,并且NaN忽略三元条件运算的未使用分支.

  • _"它不仅仅是一个数字函数而不是`pow`"_嘿,不错的尝试;) (2认同)

Rus*_*lan 6

下面是一个示例,演示返回非 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)


And*_* H. 5

我会尝试的另一种情况是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 = 0b = 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 输出。

注意:这个推理可以应用于任何函数,包括内置运算符。