将 NaN 或 Inf 与 0 相乘得到 0

Mic*_*ael 2 c++ nan

我有一组值 a[i]

然后我计算

for(...){
  b[i] = log(a[i]);
}
Run Code Online (Sandbox Code Playgroud)

然后我总结

for(...){
  s += c[i] * b[i];
}
Run Code Online (Sandbox Code Playgroud)

到目前为止这没有问题。

但对于某些人来说,ia[i]可能为零并导致b[i] = log(0) = -Inf. 对于这些i,c[i]也为零 - 这些是一些无效的数据点。但zero*-Inf似乎给了NaN,我的总和搞砸了......

有没有办法c[i] * b[i]c[i]is = 0时总是有= 0?

我看到的唯一方法是将所有零设置a[i]为一个小的非零值或检查零,但可能有更好的解决方案。

我使用 C++ 和std数学函数,但我正在寻找一种尽可能通用的方法。

Zer*_*ero 5

简而言之:

for(...){
  double tmp = c[i] * b[i];
  s += (tmp == tmp) ? tmp : 0;
}
Run Code Online (Sandbox Code Playgroud)

0 * InfNaN通过定义(IEEE 754标准) -所以你不能改变这种行为。

测试数字是否为 nan 的“教科书”方式是与自身进行比较,例如:

if (x != x)
    std::cout << "x is nan" << std::endl;
else
    std::cout << "x is not nan" << std::endl;
Run Code Online (Sandbox Code Playgroud)

这取决于这样一个事实 NaN不等于任何事物,包括它自身。(再次根据定义)。

C++11 引入了is_nan,它更具可读性,如果你没有 C++11,我建议你自己写

bool isnan(double arg) { return arg != arg; }
Run Code Online (Sandbox Code Playgroud)

事实上,NaN与任何事情都没有比较,所以以下都有效:

if (x < y) std::cout << "x is not nan" << std::endl;
if (x > y) std::cout << "x is not nan" << std::endl;
if (x <= y) std::cout << "x is not nan" << std::endl;
if (x >= y) std::cout << "x is not nan" << std::endl;
Run Code Online (Sandbox Code Playgroud)

这种令人惊讶的行为背后的原因(请参阅此问题)是能够使用上述条件进行编码以过滤掉NaN代码,这使得代码非常简单,并且还NaNnot setunknown值提供了合适的哨兵。