簡體   English   中英

使C浮點數精確嗎?

[英]Making C floats precise?

在C語言中,設置浮點數后,

int main(int argc, char *argv[]) {
    float temp = 98.6f;
    printf("%f\n", temp);
    return 0;
}

似乎總是出現某種舍入錯誤,

98.599998

但是當我說得更精確時,

float temp = 96.600000f;

它仍然打印一個不同的數字。 應該如何解決?

它仍然打印一個不同的數字。 應該如何解決?

如果要精確的十進制值,請使用其他數據類型。

二進制浮點數精確的-只是它們是精確的二進制值。

同樣,例如,如果要表示以3為底的數字,則十進制是不精確的。 沒有精確的二進制表示形式為0.1十進制,就像沒有精確的十進制表示形式為“三分之一”一樣。

弄清楚您的需求是什么,並使用匹配它們的數據類型就可以了。 對於精確的十進制值,最好使用第三方庫...或保留一個邏輯上已知可以按100或10,000或其他比例縮放的整數。

這是以二進制形式表示十進制數字的基本限制。 二進制浮點數以2的冪表示,而十進制數以10的冪表示,並且C的float無法完全表示所有十進制數。

您的示例號碼96.1可以寫為:

96.1 = 9*10^1 + 9*10^0 + 1*10^-1

為了用二進制表示,可以得到整數96:

96 = 1*2^6 + 1*2^5

但是在基數2中表示0.1是有問題的。二進制文件中前幾個小數位的位數是:

2^-1 = 0.5
2^-2 = 0.25
2^-3 = 0.125
2^-4 = 0.0625
2^-5 = 0.03125
2^-6 = 0.015625
2^-7 = 0.0078125
2^-8 = 0.00390625
2^-9 = 0.001953125
... and so on

因此,您需要以某種方式使用這些位置值的組合來將十進制的值總計大約為0.1。 因此,您必須以b0.0001(d0.0625)作為小於d0.1的第一個位置,並添加更多的較小位置值來使其越來越接近0.1。 例如:

b0.001      = d0.125      // too high, try lower
b0.0001     = d0.0625     // too low, so add smaller places
b0.00011    = d0.09375    // good, closer... rounding error is 0.0625
b0.000111   = d0.109375   // oops, a little high
b0.00011001 = d0.09765625 // getting better - how close do you need?
...

依此類推-您明白了。 因此,由於基本表示形式,二進制值只能近似於小數。

關於浮點舍入誤差和表示限制的文章很多。 絕對值得對此主題進行一些背景閱讀。

有幾種方法可以解決此問題:

  • 使用float但請注意其局限性,並仔細設計算法以最大程度地減少舍入誤差
  • 使用精確的十進制表示形式,例如BCD(二進制編碼的十進制),該形式在金融系統中用於避免舍入錯誤
  • 使用固定的數據類型,其中數字表示為整數的分數,並且僅在計算結束時轉換為浮點以顯示結果。

添加尾隨零將無濟於事。

問題是32位浮點不能精確表示96.6周期。

這不是隨機挑選數字來填補您遺漏的內容; 將其四舍五入為它可以表示的最接近的數字。

它依賴於平台,但是通常無法准確表示98.6之類的數字。

您可以做的是使用諸如"%.2f"類的printf精度說明符來“舍入”所顯示的數字。

沒有簡單的答案。 它與浮點數在內存中的表示方式有關,但是我們傾向於認為它們可以表示所有實數。 他們不能。 如果要精確使用浮點數,請考慮小於或大於范圍,而不是試圖將它們等同。 在您的示例中,嘗試使用%f2.1(或類似格式)在小數點右邊打印少量的數字。

贈與是float一詞。

它由尾數和指數組成。 該值是它可以在有限的位數(例如pi)中獲得的最佳表示。

因此,在出現舍入錯誤時,請不要使用相等性。 您可以采取措施將其最小化,但這需要一些講座和一本教科書。

順便說一句-不要用浮子賺錢。 更好地使用整數並以美分/便士/ ...來計算...

暫無
暫無

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

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