2009-02-02 66 views
7

我收到的一項最近的家庭作業要求我們採取措辭,在計算機上執行時可能會造成精度損失,並對其進行修改,以避免造成損失。避免精度損失的最佳算法?

不幸的是,這樣做的方向尚未明確。通過觀察正在執行的各種示例,我知道有一些方法可以做到這一點:使用泰勒級數,如果涉及平方根使用共軛,或者在減去兩個分數時找到共同的分母。

但是,我在準確發現精確度丟失時會發生一些麻煩。到目前爲止,我唯一知道的是,當你減去接近於相同的兩個數字時,由於高位數字很重要,所以會出現精度損失,並且你會從四捨五入中丟失這些數字。

我的問題是我應該尋找哪些其他常見情況,以及哪些被認爲是接觸它們的「好」方法?

例如,這裏有一個問題:

f(x) = tan(x) − sin(x) when x ~ 0 

什麼是評價這一點這三個選項的最佳和最差的算法:

(a) (1/ cos(x) − 1) sin(x), 
(b) (x^3)/2 
(c) tan(x)*(sin(x)^2)/(cos(x) + 1). 

我明白,當x接近零,tan(x)和sin(x)幾乎相同。我不明白如何或爲什麼這些算法對於解決問題更好或更差。

回答

5

通常使用的另一個經驗法則是:當添加一長串數字時,開始從最接近零的數字開始添加,並以最大數字結束。

解釋爲什麼這是好的只是棘手。當你爲大數添加小數時,它們有可能被完全丟棄,因爲它們比當前大數的尾數小。就拿這樣的情況:

a = 1,000,000; 
do 100,000,000 time: 
    a += 0.01; 

如果0.01比最低的尾數數字越小,則循環不執行任何操作而最終的結果是==百萬 但如果你這樣做是這樣的:

a = 0; 
do 100,000,000 time: 
    a += 0.01; 
a += 1,000,000; 

比低數字慢慢增長,你更可能最終接近一個== 2,000,000這是正確的答案。
這是一個極端的例子,但我希望你明白。

4

當我還是一名本科生時,我不得不接受一個數學課,而且這是非常痛苦的。無論如何,IEEE 754是典型的由現代CPU實現的浮點標準。瞭解它的基礎知識是有用的,因爲這給你很多關於不該做什麼的直覺。它的簡單解釋是計算機存儲浮點數,如基數爲2的科學記數法,指數和尾數的位數都是固定的。這意味着數字的絕對值越大,其表示的精確度越低。對於IEEE 754中的32位浮點數,一半的可能位模式表示-1和1之間,即使可以用32位浮點數表示大約10^38的數字。對於大於2^24(大約16.7百萬)的值,32位浮點數不能完全表示所有整數。

這意味着什麼,你是,你通常需要避免以下幾點:

  1. 有當最後的答案有望成爲小中間值大。
  2. 在大數上加/減小數。例如,如果你寫的東西,如:用於

    (浮點指數= 17000000;指數< 17000001;指數++){}

這個循環將永遠不會終止監守17000000 + 1向下取整到17000000。 如果你有這樣的事情:

float foo = 10000000 - 10000000.0001 

foo的值是0,沒有-0.0001,由於舍入誤差。

1

另一件事情,以避免被減去幾乎是相同的數字,因爲這也可能導致對舍入誤差的敏感性增加。對於接近0的值,cos(x)將接近於1,所以1/cos(x)-1是那些你希望儘可能避免的減法之一,所以我應該說(a)應該被避免。

2

我的問題是什麼是我應該尋找 一些其他 常見的情況,什麼被認爲是「好」接近他們的 方法呢?

有幾種方法可以導致嚴重或甚至災難性的精度損失。

最重要的原因是浮點數有位數量有限,e.g..doubles有53位。這意味着,如果您的「無用」數字不屬於解決方案的一部分,但必須存儲,您將失去精確度。

例如(我們使用十進制類型示範):

2.598765000000000000000000000100 -

2.598765000000000000000000000099

有趣的部分是100-99 = 1的答案。由於2.598765在兩種情況下均相同,因此它 不會更改結果,但會浪費8位數。更糟糕的,因爲電腦不 知道數字是沒有用的,它是被迫來存儲它和之後的CRAM 21個零, 浪費在所有29位。不幸的是,沒有辦法規避差異, ,但還有其他的情況,例如, exp(x)-1這是物理學中經常出現的函數。

0附近的exp函數幾乎是線性的,但它強制執行1作爲前導數字。因此,與12個 顯著數字 EXP(0.001)-1 = 1.00100050017 - 1 = 1.00050017e-3

如果我們使用而不是函數的expm1()中,使用泰勒級數:

1 + X + X3^2/2 + x^3/6 ...-1 =

X + X^2/2 + X^3/6 =:的expm1(X)

的expm1(0.001)= 1.00500166667e -3-

好得多。

第二個問題是函數的斜率非常陡,如x的切線接近pi/2。 tan(11)的斜率爲50000,這意味着由於舍入誤差 而引起的任何小偏差都將被因子50000放大!或者你有奇點,例如,結果接近0/0,這意味着它可以有任何值。

在這兩種情況下,您都會創建一個替代函數,簡化原始函數。突出顯示不同的解決方案是沒有用的,因爲如果沒有經過培訓,您根本就不會「首先」看到問題。

一本很好的學習和訓練的書:Forman S. Acton:Real Computing made real