2015-10-06 160 views
1

我有一组值a[i]将NaN或Inf乘以0并得到0

然后我计算

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

浏览数组并将所有NaN替换为0? –

回答

3

简而言之:

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

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

测试的“教科书”的方式,如果一个号码是男是与自身比较,如:

if (x != x) 
    std::cout << "x is nan" << std::endl; 
else 
    std::cout << "x is not nan" << std::endl; 

这依赖于一个事实,即NaN不等于任何东西,包括自己。 (再次定义)。

C++ 11引入is_nan这是更具可读性,如果你没有C++ 11我建议写自己喜欢

bool isnan(double arg) { return arg != arg; } 

事实上,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; 

这背后令人惊讶的行为的原因(see this question)是能够使用上述条件筛选出NaN,使非常简单的代码代码,并且还使NaN成为not setunknown值的合适哨兵。

2

当分配b[i]你可以用下面的结构:

b[i] = (a[i] == 0) ? 0 : log(a[i]); 

或者浮点比较(阅读为什么这个解决方案也适用于当前问题的意见的情况下,但可能不是好主意,在所有):

b[i] = (fabs(a[i]) < DBL_EPSILON) ? 0 : log(a[i]); 
+0

为什么? a [i] == 0完美工作 – galinette

+1

您可能会误解DBL_EPSILON。在任何情况下,与DBL_EPSILON比较是一个非常糟糕的主意。原来的比较为零是很好的。但对于原始问题,比较'c [i]'0比比较'a [i]'更有意义,因为当'a [i] == 0 && c [i]!= 0'时,结果可能' t是正确的,你可能想要NaN或INF。 – JSF

+1

这就是询问者询问的问题(当c [i] = 0时''c [i] * b [i] = 0'),但可能不是他们想要的:正如指出'b [i]'是'nan'和'c [i]'应该是零,但不是由于舍入误差,总和仍然是'nan'。使用'DBL_EPSILON'不会解决这个问题,因为根据计算,浮点计算中的错误可能是任意大的。 请注意,如果您的_know_'c [i]'将为零(因为它已设置为零,而不是由于计算结果可能只接近零),所以此答案没有问题。 – Zero

4
for (...) { 
    s += c[i] * (std::isinf(b[i]) ? 1 : b[i]); 
} 

for (...) { 
    s += (c[i] == 0 ? 0 : c[i] * b[i]); 
} 
+2

要完全回答这个问题,你需要isinf,而不是isnan – galinette

+0

你是对的,我解决了这个问题。而且我还添加了另一个不需要isinf的选项:-) –

+0

第二种选择只是绕过这个问题。尼斯。 – ecotax

2

你可以使用一些正在CMATH无限的考验;是这样的:

s += (c[i] == 0 && std::isinf(b[i])) ? 0 : c[i] * b[i]; 
+2

要完全回答这个问题,你需要isinf,而不是isnan – galinette

+0

糟糕,是的,isinf当然。 – ecotax