[英]Rounding floats in C
While testing the float type and printing it with it's format specifier %f
I was testing it's rounding methods. 在测试浮点类型并使用格式说明符
%f
对其进行打印时,我正在测试其舍入方法。
I've declared the variable as float and gave it the value 5.123456. 我已将变量声明为float,并为其指定了值5.123456。 As you know float must represent at least 6 significant figures.
如您所知,浮点数必须至少代表6个有效数字。
I then changed it's value to 5.1234567 and printed the value with the %f
. 然后,我将其值更改为5.1234567并用
%f
打印该值。 It baffles me why it prints out as 5.123456. 这让我感到困惑,为什么它输出为5.123456。 But if I change the variable value to 5.1234568, it prints out as 5.123457.
但是,如果我将变量值更改为5.1234568,它将输出为5.123457。 It rounds properly.
正确舍入。
If I haven't made myself clear or the explanation is very confusing: 如果我不清楚,或者解释很混乱:
float a = 5.1234567
printf("%d", a);
// prints out as 5.123456
float a = 5.1234568
printf("%d", a);
// prints out as 5.123457
I've compiled using CodeBlocks and MinGW, same result. 我已经使用CodeBlocks和MinGW进行了编译,结果相同。
OP is experiencing the effects of double rounding OP正在经历双舍入的影响
First, the values 5.123456, 5.1234567, etc. are rounded by the compiler to the closest representable float
. 首先,编译器将值5.123456、5.11234567等舍入到最接近的可表示
float
。 Then printf()
is rounding the float
value to the closest 0.000001 decimal textual representation. 然后
printf()
将float
值四舍五入到最接近的0.000001十进制文本表示形式。
I've declared the variable as float and gave it the value 5.123456.
我已将变量声明为float,并为其指定了值5.123456。 As you know float must represent at least 6 significant figures.
如您所知,浮点数必须至少代表6个有效数字。
A float
can represent about 2^32 different values. float
可以表示大约2 ^ 32个不同的值。 5.123456 is not one of them. 5.123456不是其中之一。 The closest value a typical
float
can represent is 5.12345600128173828125 and that is correct for 6 significant digits: 5.12345... 典型
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
With 5.1234567, the closest float
has an exact value of 5.123456478118896484375. 对于5.1234567,最接近的
float
的精确值为5.123456478118896484375。 When using "%f"
, this is expected print rounded to the closest 0.000001
or 5.123456
当使用
"%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
Significant digits is not the number of digit after the decimal point. 有效数字不是小数点后的位数。 It is the number of digits starting with the left-most (most significant) digit.
它是从最左(最高有效)位开始的位数。
To print a float
to 6 significant figures, use "%.*e"
. 要将
float
打印为6位有效数字,请使用"%.*e"
。
See Printf width specifier to maintain precision of floating-point value for more details. 有关更多详细信息,请参见Printf宽度说明符以保持浮点值的精度 。
float x = 5.1234567;
printf("%.*e\n", 6 - 1, x); // 5.12346e+00
// x xxxxx 6 significant digits
There is no exact float representation for the number 5.1234567 you intend to show here. 您要在此处显示的数字5.1234567没有确切的浮点表示形式。
If you check here: https://www.h-schmidt.net/FloatConverter/IEEE754.html 如果您在此处查看: https : //www.h-schmidt.net/FloatConverter/IEEE754.html
You can see that this number is converted into 5.1234565, or the double 5.1234564781188965 and this rounds down, 您会看到此数字已转换为5.1234565或双精度的5.1234564781188965,并将其四舍五入,
While the number 5.1234568 is representable in float, and has a double representation of 5.123456954956055, and this rounds up. 数字5.1234568用浮点数表示,并且具有5.123456954956055的双精度表示,因此将其取整。
There are two levels of rounding going on: 舍入分为两个级别:
It will become obvious if you print the value with more digits. 如果您打印更多位数的值,这将变得显而易见。
What it comes down to is that the mantissa of a float has 23 bits and this is not the same as 6 decimal digits (or any number of digits really). 得出的结论是,浮点数的尾数有23位,这与6个十进制数字(或实际上是任意数字)不同。 Even some apparently simple values like 0.1 don't have an exact float representation.
甚至一些看似简单的值(例如0.1)也没有精确的浮点表示形式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.