簡體   English   中英

浮點舍入效果說明

[英]Explanation for floating point rounding effect

#include <stdio.h>
int main() {
    printf("%.14f\n", 0.0001f * 10000000.0f);  // 1
    printf("%.14f\n", 0.001f * 1000000.0f);  // 2
    printf("%.14f\n", 0.01f * 100000.0f);  // 3
    return 0;
}

神箭

這段代碼的輸出是:

1000.00000000000000
1000.00006103515625
1000.00000000000000

我知道,小數不能用浮點數准確表示。 但是為什么第 1 行和第 3 行計算正確,而第 2 行卻沒有? 你對這里發生的事情有清楚的解釋嗎?

有時累積舍入(在 OP 樣本中每個 3 步)的結果與數學/十進制相同,有時則不同。 @史蒂夫峰會@史蒂夫峰會


詳細說明這里發生了什么?

每行代碼有 3 個潛在舍入步驟:

  • 源代碼float 回想一下常見的float的形式: some_limited_integer * 2 some_power

  • 帶舍入的float乘法

  • 打印四舍五入到小數點后 14 位*1float


對於printf("%.14f\\n", 0.0001f * 10000000.0f); // 1 printf("%.14f\\n", 0.0001f * 10000000.0f); // 1

  • 代碼0.0001ffloat ,值為 0.00009999999747378751635555145263671875

  • 0.0000999999747378751635555145263671875 * 10000000.0 --> 999.999974737875163555145263671875 --> 舍入到最接近的 10 float -->

  • 1000.0 --> "1000.00000000000000"


對於printf("%.14f\\n", 0.001f * 1000000.0f); // 2 printf("%.14f\\n", 0.001f * 1000000.0f); // 2

  • 代碼0.001ffloat ,值為 0.001000000047497451305389404296875

  • 0.001000000047497451305389404296875 * 1000000.0 --> 1000.000047497451305389404296875 --> 四舍五入到最接近的float --> 100562.

  • 1000.00006103515625 --> "1000.00006103515625"


在#1 中,四舍五入是向下的,然后向上 - 趨於取消。
在 #2 中,四舍五入是向上和向上的 - 導致明顯的雙四舍五入效果。

粗略地說,每一步都可能注入高達 1/2 ULP 的錯誤。


其他注意事項: 1) 替代舍入模式。 以上使用舍入到最近。 2)弱庫。 以上假設質量printf()


*1在 OP 的樣本中,沒有舍入誤差。 一般來說,用"%f"打印float可以舍入。

回答這個問題的另一種方法是說,你沒有得到一個“錯誤”的答案,兩個“正確”答案。 你實際上得到了三個“正確”的答案,其中“正確”的意思是“和預期的一樣好”。

類型float只給你大約 7 個十進制數字的精度。 因此,對於 1000 范圍內的數字,這是小數點后三位。 所以把程序改成這樣:

printf("%.3f\n", 0.0001f * 10000000.0f);
printf("%.3f\n", 0.001f * 1000000.0f);
printf("%.3f\n", 0.01f * 100000.0f);

輸出是:

1000.000
1000.000
1000.000

沒有差異,所有答案顯然都是正確的。

或者,用指數表示法進行計算,小數點前一位,后 6 位。

printf("%.6e\n", 0.0001f * 10000000.0f);
printf("%.6e\n", 0.001f * 1000000.0f);
printf("%.6e\n", 0.01f * 100000.0f);

1.000000e+03
1.000000e+03
1.000000e+03

同樣,所有答案都相同。

這可能看起來像是“作弊”:我們碰巧知道在我們可以看到的右邊的數字中有一些“有趣”的事情,所以以這種方式壓制它們並讓它看起來是不是錯了好像所有的答案都一樣? 我不打算回答這個問題,除了指出當你在做浮點運算時,幾乎總是有一些東西在右邊,你在四舍五入和抑制——這只是一個問題度。

暫無
暫無

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

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