格式化与四舍五入
本文将讨论在格式化输出浮点数时的四舍五入问题,为了便与讨论,将问题分为原始数据是浮点数,以及通过计算得到的浮点数两种情况。
本次测试使用的编译器为 Visual C++ 2015
。
前置知识
浮点数有两类:
- float,单精度浮点型,有效位数为7位,格式化参数为
%f
- double,双精度浮点型,有效位数为16位,格式化参数为
%lf
指定小数位方法的格式化语法:printf("%.*f", nDecimal, fValue)
。
原始数据是浮点数
一般采用 printf("%M.Nf", dValue)
的语法进行格式化。M
表示输出字符的最小宽度,N
表示输出小数位数,当N
为0时,表示不输出小数和小数点。当小数位不够N
位,对于的位数补0。
以下是例子:
void test_format_float()
{
double dTestZero = 1.2;
printf("0.1 %.0f\n", dTestZero);
dTestZero = 1.3;
printf("0.2 %.0f\n", dTestZero);
dTestZero = 1.4;
printf("0.3 %.0f\n", dTestZero);
dTestZero = 1.5;
printf("0.4 %.0f\n", dTestZero);
dTestZero = 1.6;
printf("0.5 %.0f\n", dTestZero);
double dTest = 1.2345678;
printf("1.1 %4.0f\n", dTest);
printf("1.2 %4.1f\n", dTest);
printf("1.3 %4.2f\n", dTest);
printf("1.4 %4.3f\n", dTest);
printf("1.5 %4.4f\n", dTest);
printf("1.6 %4.5f\n", dTest);
printf("1.7 %4.6f\n", dTest);
double dTest2 = 8.7654321;
printf("2.1 %4.0f\n", dTest2);
printf("2.2 %4.1f\n", dTest2);
printf("2.3 %4.2f\n", dTest2);
printf("2.4 %4.3f\n", dTest2);
printf("2.5 %4.4f\n", dTest2);
printf("2.6 %4.5f\n", dTest2);
printf("2.7 %4.6f\n", dTest2);
}
输出结果如下:
小结:当按%M.Nf
格式化输出浮点数,输出是满足四舍五入的规则。
原始数据是计算出来的浮点数
根据计算依赖的数据类型,可分为以下三种:
- 浮点数和浮点数
- 浮点数和整数
- 整数和整数
浮点和浮点
这种情况和原始数据是浮点数
是一样规则,此处不再赘述。
浮点数和整数
根据计算规则,此时会将整数提升为浮点数,然后进行计算,情况原始数据是浮点数
。
整数和整数
整数运算是没有四舍五入,当计算结果有小数时,会舍弃掉全部小数,这种规则,在某些情况下不是我们期望的。因此,需要一种方法,得到此场景下的小数显示。
梳理现有的,有两种方案:
- 加上特定数值,并以
%d
输出。
这种方法是给计算结果加上0.5
,对计算结果的1位小数进行四舍五入。
double dCount = 2087;
int nUnit = 100;
// 不保留小数,对整形结果进行四舍五入。
printf("%d\n", (int)(dCount/nUnit + 0.5));
这种做法的缺点是,只适合四舍五入1位小数,不适合其他场合,而且这个0.5
在这里是个魔幻数字,可读性不好。
- 将计算结果强制转换为浮动类型,再进行计算,例如:
int a = 123456;
int b = 100000;
printf("5.0 %1.1f\n", a / b);
printf("5.1 %1.1f\n", (double)a / b);
printf("5.2 %1.2f\n", (double)a / b);
printf("5.3 %1.3f\n", (double)a / b);
printf("5.4 %1.4f\n", (double)a / b);
printf("5.5 %1.5f\n", (double)a / b);
printf("5.6 %1.6f\n", (double)a / b);
这种方案,适合各种不同小数位数的四舍五入场景,无魔幻数字,值得推荐。
小结
对浮点数的格式化输出,可采用 %M.Nf
的格式,输出是按照四舍五入的规则。
当需要显示两个整形值的精确除法结果时,建议将其中一个变量强制转换为double
类型再进行计算,简单直接。
参考文章: