2013-05-02 91 views
1

在C++編程中,我什麼時候需要擔心精度問題?舉一個小例子(它可能不是雖然是完美的一個),計算機精度:我應該什麼時候擔心它?

std::vector<double> first (50000, 0.0); 
std::vector<double> second (first); 

難道是可能的,second[619] = 0.000000000000000000000000000(我的意思是一個很小的值)。或者SUM = second[0]+second[1]+...+second[49999] => 1e-31?或SUM = second[0]-second[1]-...-second[49999] => -7.987654321e-12

我的問題:

  1. 難道是一些小的干擾與double型數字打交道?
  2. 什麼可能導致這些小干擾?即舍入誤差變大?你能列出他們嗎?如何採取預防措施?
  3. 如果在某些操作中可能會有小的干擾,那麼是否意味着在這些操作之後,使用if (SUM == 0)危險?那麼應該總是使用if (SUM < SMALL)來替代,其中SMALL被定義爲非常小的值,例如1E-30
  4. 最後,小干擾可能導致負值嗎?因爲如果可能的話,我應該更好地使用if (abs(SUM) < SMALL)來代替。

任何經驗?

回答

4

這是浮點精度很好的參考文獻:What Every Computer Scientist Should Know About Floating-Point Arithmetic

一個比較重要的部分是災難性的取消時操作數都受到 舍入誤差發生

災難性取消。例如在二次公式中,出現表達式 b2-4ac。數量b2和4ac由於是浮點乘法的結果而受到四捨五入的 錯誤的影響。 假設它們四捨五入到最接近的浮點數 ,所以精確到0.5 ulp以內。當它們被扣除時, 取消可能導致許多準確的數字消失, 主要留下由舍入誤差污染的數字。因此, 差異可能會有許多ulps的錯誤。例如,考慮b = 3.34,a = 1.22和c = 2.28。 b2 - 4ac的確切值是.0292。但b2輪到11.2和4ac輪到11.1,因此最終答案 是.1這是一個70 ulps的錯誤,儘管11.2 - 11.1正好是 等於.16。減法沒有引入任何錯誤,而是暴露了早期乘法中引入的錯誤。

當減去確切的已知量時,會發生良性取消。 如果x和y沒有舍入誤差,那麼通過定理2,如果用保衛位數完成相減,則差異x-y具有非常小的相對誤差(小於2)。

顯示災難性取消的公式有時可以重新排列以消除該問題 。再次考慮二次 式

1
對於

您的具體實例中,0具有一個精確的表示爲雙,和精確地將0加至雙不改變其值。

此外,和其他任何你放入變量的值一樣,你在數組中初始化的數字也不會神祕地改變。當計算結果不能精確地表示爲浮點數時,您只能取整。

爲了給出關於「干擾」的更好的意見,我需要知道你的代碼執行的計算種類。

相關問題