我有一组值a[i]
。
然后我计算
for(...){
b[i] = log(a[i]);
}
然后我总结了
for(...){
s += c[i] * b[i];
}
到目前为止没问题。
但是对于某些i
,我的a[i]
可能为零并导致b[i] = log(0) = -Inf
。对于这些i
,c[i]
也为零 - 这些是一些无效的数据点。但是zero*-Inf
似乎给了NaN
,我的总和搞砸了......
当c[i] * b[i]
= 0时,有没有办法让c[i]
= 0?
我看到的唯一方法是将所有零a[i]
设置为一个小的非零值或检查零,但可能有更好的解决方案。
我使用C ++和std
数学函数,但我正在寻找一种尽可能通用的方法。
答案 0 :(得分:4)
for (...) {
s += c[i] * (std::isinf(b[i]) ? 1 : b[i]);
}
for (...) {
s += (c[i] == 0 ? 0 : c[i] * b[i]);
}
答案 1 :(得分:3)
简而言之:
where
根据定义, where
是for(...){
double tmp = c[i] * b[i];
s += (tmp == tmp) ? tmp : 0;
}
(IEEE 754标准) - 所以你无法改变这种行为。
测试数字是否为nan的'教科书'方法是与自身进行比较,例如:
0 * Inf
这取决于NaN
不等于任何事物的事实,包括它自己。 (再次按定义)。
C ++ 11引入了is_nan,它更具可读性,如果你没有C ++ 11,我建议你自己编写
if (x != x)
std::cout << "x is nan" << std::endl;
else
std::cout << "x is not nan" << std::endl;
事实上,NaN
并不能与任何事物进行真实比较,因此以下各项都有效:
bool isnan(double arg) { return arg != arg; }
这种令人惊讶的行为背后的原因(see this question)是能够使用上述条件进行编码以过滤掉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;
成为合适的代码NaN
或NaN
值的哨兵。
答案 2 :(得分:2)
分配b[i]
时,您可以使用以下构造:
b[i] = (a[i] == 0) ? 0 : log(a[i]);
或者在浮点比较的情况下(阅读评论为什么这个解决方案也适用于当前问题,但可能根本不是好主意):
b[i] = (fabs(a[i]) < DBL_EPSILON) ? 0 : log(a[i]);
答案 3 :(得分:2)
你可以在cmath中使用测试数量为无限;类似的东西:
s += (c[i] == 0 && std::isinf(b[i])) ? 0 : c[i] * b[i];