2011-08-08 47 views
9

我有一些數學(在C++中),其中似乎將生成一些非常小的,接近零的數字(我懷疑trig函數調用是我真正的問題),但我想檢測這些情況,以便我可以更詳細地研究它們。如何檢查和處理非常接近零的數字

我目前正在嘗試以下,是否正確?

if (std::abs(x) < DBL_MIN) { 
    log_debug("detected small num, %Le, %Le", x, y); 
} 

二,數學的本質是三角函數的性質(又名採用了很多弧度/度的轉換和sin/cos/tan電話等),我可以做什麼樣的變革,以避免數學錯誤?

很顯然,乘法運算可以使用log transform - 還有什麼?

+0

我們可以請看一個上述數學的例子,以便我們可以設計一些優雅的東西?當我可以在零點附近緩慢地改變結果時,我腦海中的東西就像'cos x - 1',必須仔細選擇容差。 –

+1

至於避免下溢的轉換,最直接的就是泰勒擴展你的表達式,並使用小的參數。例如,而不是'1-cos(x)'使用'x * x/2'來表示'x'小於某個臨界值。 –

回答

2

如果x是一個雙,那麼一個問題,這種方法是,你不能x區分是合法零,x是正值比DBL_MIN小。所以如果你知道x永遠不可能是合法的零,並且你想知道什麼時候發生了下溢,這將會起作用。

您還可以嘗試捕獲SIGFPE信號,該信號在任何時候出現數學錯誤(包括浮點下溢)時將在POSIX兼容系統上觸發。請參閱:http://en.wikipedia.org/wiki/SIGFPE

編輯:很明顯,DBL_MIN是不是最大的負值,一個雙能裝,它是最小正normalized值雙能容納。所以只要價值不能爲零,你的方法就沒有問題。

另一個有用的常數是DBL_EPSILON這是最小的double值,可以添加到1.0而不會返回1.0。請注意,這是一個比DBL_MIN大得多的值。但它可能對你有用,因爲你正在做的三角函數可能趨向於1而不是向0傾向。

2

由於您使用的是C++,最常用的方法是使用標頭<limits>中的std::numeric_limits

例如:

template <typename T> 
bool is_close_to_zero(T x) 
{ 
    return std::abs(x) < std::numeric_limits<T>::epsilon(); 
} 

實際公差被大量使用取決於你的問題。請用一個具體的用例來完成你的問題,這樣我可以提高我的答案。

還有std::numeric_limits<T>::min()std::numeric_limits<T>::denorm_min()這可能是有用的。第一個是類型爲T(等於FLT/DBL/LDBL_MIN,等於<cfloat>)的最小的正非非標準化值,第二個是類型爲T(不等於<cfloat>)的最小正值。

[您可能會發現this document有用的信息,如果你不放心浮點數的表示。]

+0

可能在今天晚些時候,我弄清楚了哪些部分的問題導致了問題。感謝C++珍聞! – Petriborg

+0

'DBL_MIN'是最小的正數**正規化的**'double'值,所以它將對應於'min()'而不是'denorm_min()'。 –

+0

@DanielFischer:的確,謝謝。糾正。 –

0

第一if檢查時你的價值爲零將僅實際上是真實的。

關於第二個問題,你意味着大量的轉換。相反,選擇一個單位(deg或rad)並在該單位中執行所有計算操作。然後在最後做一個單一的轉換到另一個值,如果你需要。

+0

'DBL_MIN'是最小的正**正規化**雙倍值,有更小的正雙倍。 –

5

相反,人們普遍相信,DBL_MIN不是最小的正double值,但最小的正標準化double值。通常 - 對於64位ieee754 doubles - 它是2 -1022,而最小的正數double的值是2 -1074。因此

目前,我正在嘗試以下,是正確的嗎?

if (std::abs(x) < DBL_MIN) { 
    log_debug("detected small num, %Le, %Le", x, y); 
} 

可能有一個肯定的答案。所述條件檢查x是否爲規格化(也稱爲低於正常)號碼或±0.0。不知道更多關於你的具體情況,我不知道這個測試是否合適。非規格化的數字可以是合理的計算結果,也可以是正確結果爲0的四捨五入的結果。當數學上正確的結果爲0時,四捨五入也可能產生遠大於DBL_MIN的數量,因此可能有一個更大的閾值是明智的。

+0

感謝您對此提出的意見 - 問題仍在繼續,但我沒有時間去實際回去處理。我可能會嘗試發佈一個更聰明的問題。 – Petriborg