[英]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.