首頁  >  文章  >  後端開發  >  為什麼 C 浮點運算會產生意想不到的結果,我們該如何減輕這些精確度異常?

為什麼 C 浮點運算會產生意想不到的結果,我們該如何減輕這些精確度異常?

Barbara Streisand
Barbara Streisand原創
2024-11-04 21:38:02813瀏覽

Why does C   floating-point arithmetic produce unexpected results, and how can we mitigate these precision anomalies?

C 浮點精度異常和分辨率

儘管C 中的浮點數廣泛使用,但它們在精度方面表現出局限性。考慮以下程式碼片段:

<code class="cpp">double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;

此程式碼輸出 0.2999999999999999889,而不是預期的 0.3。造成這種差異的原因是變數 a 並未完全儲存為 0.3 雙精度浮點數,而是由於浮點值的有限表示而儲存為它的近似值。

當出現更令人驚訝的行為時,會出現以下情況: a 重複添加 50 次:

<code class="cpp">double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;

這段程式碼令人驚訝地輸出 15.000000000000014211 而不是 15.0。這是因為每次加法都會累積近似誤差,導致累積誤差大於原始精度。

解決精度異常

要獲得精確的結果,需要避免將輸出精度設定為大於數字類型的可用數字至關重要。這可以使用std::numeric_limits 類別來實現:

<code class="cpp">#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}</code>

此程式碼使用digits10成員函數將精確度設定為雙精確度浮點數的最​​大可用位數,即15

浮點運算的限制

雖然提供的解決方案最大限度地減少了精度誤差,但重要的是要認識到浮點運算具有固有的局限性。如果一個循環涉及數千次迭代,即使精度設定適當,累積誤差也可能變得很大。在這種情況下,替代資料類型,例如定點數或有理數,可能更適合維護精確值。

以上是為什麼 C 浮點運算會產生意想不到的結果,我們該如何減輕這些精確度異常?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn