簡體   English   中英

在C ++中進行數學運算時,浮點誤差如何傳播?

[英]How does floating point error propagate when doing mathematical operations in C++?

假設我們已經聲明了以下變量

float a = 1.2291;

float b = 3.99;

float變量有精度6,(如果我理解正確的話)意味着計算機實際存儲的數量與你想要的實際數量之間的差異將小於10^-6

這意味着ab都有一些小於10^-6錯誤

所以,在電腦內的a實際上可能是1.229100000012123b可能是3.9900000191919

現在讓我們說你有以下代碼

float c = 0;
for(int i = 0; i < 1000; i++)
      c += a + b;

我的問題是,

c的最終結果是否也會產生小於10^-6的精度誤差?

如果答案是否定的,那么我們怎么能真正知道這個精確度錯誤以及如果您按照自己的意願和任何順序應用任何類型的操作會發生什么?

浮點變量有精度6,(如果我理解正確的話)意味着計算機實際存儲的數量與你想要的實際數量之間的差異將小於10 ^ -6

這意味着a和b都有一些小於10 ^ -6的錯誤

10 -6數字是將任意常數表示為浮點數時的相對精度的粗略度量。 並非所有數字都以10 -6的絕對誤差表示。 例如,可以預期數字8765432.1大約表示單位。 如果你至少有點幸運,那么當你將它表示為float時,你將獲得8765432。 另一方面,可以預期1E-15f的絕對誤差至多約為10 -21

所以在計算機內部實際上可能是1.229100000012123而b可能是3.9900000191919

不,對不起,它的工作方式不是你編寫整個數字並為可能的錯誤添加六個零。 可以通過從前導數字計算六個零來估計誤差,而不是從最后一個數字計算。 在這里,你可以期待1.22910012123或3.990000191919。

(實際上你會得到正好1.2290999889373779296875和3.9900000095367431640625。不要忘記表示錯誤可以是負數也可以是正數,因為它是第一個數字。)

現在讓我們說你有以下代碼[...]

我的問題是,

c的最終結果是否也會產生小於10 ^ -6的精度誤差?

不會。總絕對誤差將是您使用它們的千次中每一次的ab的所有表示錯誤的總和,加上您所做的2000次加法的錯誤。 這是4000種不同的錯誤來源! 其中許多將是相同的,其中一些將碰巧相互補償,但最終結果可能不會達到10 -6相對准確度,更像是相對准確度為10 -5 (建議不計算)。

這是一個非常好的問題,許多當局已經解決了這個問題,並且本身就是一個計算機科學學科( 例如 )。 每個計算機科學家應該知道的浮點運算

浮點算術被許多人認為是一個深奧的主題。 這是相當令人驚訝的,因為浮點在計算機系統中無處不在。 幾乎每種語言都有浮點數據類型; 從PC到超級計算機的計算機都有浮點加速器; 大多數編譯器都會被要求不時編譯浮點算法; 幾乎每個操作系統都必須響應溢出等浮點異常。 本文提供了一個關於浮點的方面的教程,這些方面對計算機系統的設計者有直接影響。 它首先介紹浮點表示和舍入誤差 ,繼續討論IEEE浮點標准,最后總結了許多計算機構建器如何更好地支持浮點的例子。

(強調我的)

簡短的回答是,您無法輕松確定長鏈浮點運算的精度。

"c += a + b"這樣的操作的精度不僅取決於浮點實現的原始精度(目前幾乎總是IEEE),還取決於a,b和c的實際值。

此外,編譯器可能選擇以不同方式優化代碼,這可能導致意外問題,例如將其轉換為"c+=a; c+=b;" 或者簡單地將循環作為"tmp = a*1000; tmp += b*1000; c += tmp;" 或者編譯器將確定的一些其他變體導致更快的執行時間但是相同的結果。

最重要的是,僅通過檢查源代碼就無法進行精度分析。

出於這個原因,許多人只是使用更高精度的實現,如double或long-double,然后檢查精度問題是否已經用於所有實際目的。

如果這還不夠,那么回退總是以整數實現所有邏輯並避免浮點數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM