printf和scanf如何处理浮点精度格式?

ult*_*use 5 c floating-point precision double

请考虑以下代码段:

float val1 = 214.20;
double val2 = 214.20;

printf("float : %f, %4.6f, %4.2f \n", val1, val1, val1);
printf("double: %f, %4.6f, %4.2f \n", val2, val2, val2);
Run Code Online (Sandbox Code Playgroud)

哪个输出:

float : 214.199997,  214.199997, 214.20 | <- the correct value I wanted 
double: 214.200000,  214.200000, 214.20 |
Run Code Online (Sandbox Code Playgroud)

据我所知,它214.20具有无限的二进制表示.第一行的前两个元素具有预期值的近似值,但最后一个元素似乎根本没有近似值,这引出了以下问题:

如何做scanf,fscanf,printf,fprintf(等)函数将精度格式?

没有提供精确度,printf打印出一个近似值,但是%4.2f它给出了正确的结果.你能解释一下这些函数用来处理精度的算法吗?

Dar*_*ust 10

问题是,214.20不能用二进制表示来精确表达.几十进制数可以.因此存储了近似值.现在,当您使用printf时,二进制表示将转换为十进制表示,但它再次无法准确表达并且仅仅是近似值.

正如您所注意到的,您可以给printf一个精度来告诉它如何舍入十进制近似值.如果你没有给它一个精度,那么假设精度为6(详见手册页).

如果您在上面的示例中使用%.40ffloat和%.40lfdouble,您将获得以下结果:

214.1999969482421875000000000000000000000000
214.1999999999999886313162278383970260620117
Run Code Online (Sandbox Code Playgroud)

它们是不同的,因为有两倍,有更多的位更好地接近214.20.但正如你所看到的,当用十进制表示时,它们仍然很奇怪.

我建议阅读关于浮点数维基百科文章,以获得有关浮点数如何工作的更多见解.一本优秀的读物也是每个计算机科学家应该知道的关于浮点算术的内容