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中文網其他相關文章!