簡體   English   中英

C ++如何避免浮點算術錯誤

[英]C++ How to avoid floating-point arithmetic error

我正在編寫一個使用float遞增的循環,但我遇到了以下示例中說明的浮點算術問題:

for(float value = -2.0; value <= 2.0; value += 0.2)
    std::cout << value << std::endl;

這是輸出:

-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
1.46031e-07
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8

為什么我得到1.46031e-07而不是0 我知道這與浮點錯誤有關,但是我無法理解它為什么會發生以及我應該做些什么來防止這種情況發生(如果有辦法)。 有人可以解釋(或指向我的鏈接),這將有助於我理解? 任何輸入都表示贊賞。 謝謝!

正如其他人所說的那樣,實際數字是無限且不可數的集合,而浮點表示使用有限數量的位。 浮點數只能逼近實數,即使在很多簡單的情況下由於它們的定義也不精確。 正如您現在所看到的, 0.2實際上不是0.2而是非常接近它的數字。 當您將這些value添加到value ,您會在每一步累積錯誤。

作為替代方案,嘗試使用int s進行迭代並將結果除以將其返回到您需要的域中:

for (int value = -20; value <= 20; value += 2) {
  std::cout << (value / 10.f) << std::endl;
}

對我來說,這給了:

-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2

這是因為浮點數只有一定的離散精度。

0.2實際上不是0.2,但在內部表示為略微不同的數字。

這就是你看到差異的原因。

這在所有浮點計算中都很常見,你真的無法避免它。

沒有明確的解決方案可以避免浮點精度損失。 我建議看看下面的文章: 每個計算機科學家應該了解浮點運算

讓我們做你的循環,但增加輸出精度。

碼:

for(float value = -2.0; value <= 2.0; value += 0.2)
    std::cout << std::setprecision(100) << value << std::endl;

輸出:

-2
-1.7999999523162841796875
-1.599999904632568359375
-1.3999998569488525390625
-1.19999980926513671875
-0.999999821186065673828125
-0.79999983310699462890625
-0.599999845027923583984375
-0.3999998569488525390625
-0.19999985396862030029296875
1.460313825418779742904007434844970703125e-07
0.20000015199184417724609375
0.400000154972076416015625
0.6000001430511474609375
0.800000131130218505859375
1.00000011920928955078125
1.20000016689300537109375
1.40000021457672119140625
1.60000026226043701171875
1.80000030994415283203125

使用整數並分解:

for(int value = -20; value <= 20; value += 2)
    std::cout << (value/10.0) << std::endl;

通過一些算法書或使用互聯網了解浮點表示。 那里有很多資源。

當時,當你的東西非常接近於零時,你想要的東西似乎是某種方式來獲得零。 我們都知道我們稱這個過程為“四舍五入”。 :)所以為什么不在打印這些數字時使用它。 printf函數為這些東西提供了良好的格式化功能。 如果您不知道如何使用printf格式化,請檢查以下鏈接中的表格。 (您可以使用格式化來正確舍入和顯示數字)printf ref: http ://www.cplusplus.com/reference/cstdio/printf/?kw = printf

- 編輯 -

也許有些人知道根據數學1.99999999 ....就像2.0一樣。 唯一的區別是代表性。 但數量是一樣的。

你的浮點問題有點類似於此。 (這只是為了您的澄清。您的問題與1.9999 ....不一樣。)

暫無
暫無

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

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