2015-10-06 156 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