[英]Rounding floats in C
在測試浮點類型並使用格式說明符%f
對其進行打印時,我正在測試其舍入方法。
我已將變量聲明為float,並為其指定了值5.123456。 如您所知,浮點數必須至少代表6個有效數字。
然后,我將其值更改為5.1234567並用%f
打印該值。 這讓我感到困惑,為什么它輸出為5.123456。 但是,如果我將變量值更改為5.1234568,它將輸出為5.123457。 正確舍入。
如果我不清楚,或者解釋很混亂:
float a = 5.1234567
printf("%d", a);
// prints out as 5.123456
float a = 5.1234568
printf("%d", a);
// prints out as 5.123457
我已經使用CodeBlocks和MinGW進行了編譯,結果相同。
OP正在經歷雙舍入的影響
首先,編譯器將值5.123456、5.11234567等舍入到最接近的可表示float
。 然后printf()
將float
值四舍五入到最接近的0.000001十進制文本表示形式。
我已將變量聲明為float,並為其指定了值5.123456。 如您所知,浮點數必須至少代表6個有效數字。
float
可以表示大約2 ^ 32個不同的值。 5.123456不是其中之一。 典型float
可以代表的最接近值是5.12345600128173828125,它對於6個有效數字是正確的:5.12345 ...
float x = 5.123456f;
// 5.123455524444580078125 representable float just smaller than 5.123456
// 5.123456 OP's code
// 5.12345600128173828125 representable float just larger than 5.123456 (best)
// The following prints 7 significant digits
// %f prints 6 places after the decimal point.
printf("%f", 5.123456f); // --> 5.123456
對於5.1234567,最接近的float
的精確值為5.123456478118896484375。 當使用"%f"
,預期此打印將四舍五入到最接近的0.000001
或5.123456
float x = 5.1234567f;
// 5.123456478118896484375 representable float just smaller than 5.1234567 (best)
// 5.1234567 OP's code
// 5.1234569549560546875 representable float just larger than 5.1234567
// %f prints 6 places after the decimal point.
printf("%f", 5.1234567f); // --> 5.123456
有效數字不是小數點后的位數。 它是從最左(最高有效)位開始的位數。
要將float
打印為6位有效數字,請使用"%.*e"
。
有關更多詳細信息,請參見Printf寬度說明符以保持浮點值的精度 。
float x = 5.1234567;
printf("%.*e\n", 6 - 1, x); // 5.12346e+00
// x xxxxx 6 significant digits
您要在此處顯示的數字5.1234567沒有確切的浮點表示形式。
如果您在此處查看: https : //www.h-schmidt.net/FloatConverter/IEEE754.html
您會看到此數字已轉換為5.1234565或雙精度的5.1234564781188965,並將其四舍五入,
數字5.1234568用浮點數表示,並且具有5.123456954956055的雙精度表示,因此將其取整。
舍入分為兩個級別:
如果您打印更多位數的值,這將變得顯而易見。
得出的結論是,浮點數的尾數有23位,這與6個十進制數字(或實際上是任意數字)不同。 甚至一些看似簡單的值(例如0.1)也沒有精確的浮點表示形式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.