我想了解 C 如何处理 float 的精度损失。
这是我的简单代码:
#include <stdio.h>
#include <math.h>
int main ()
{
double a;
int i;
i = 7;
a = sqrt(i);
printf("i = %d, a = %lf\n", i, a);
printf("a * a = %lf\n", a*a);
a = 2.645751;
printf("a * a = %lf\n", a*a);
return(0);
}
下面是cc后的结果
i = 7, a = 2.645751
a * a = 7.000000
a * a = 6.999998
如果直接分配一个 float 2.645751,a * a 的结果在我看来是可以理解的。
但是如果a被赋值为sqrt(7),为什么a * a的输出没有精度损失呢?
我很难理解。
您的困惑来自 a
中实际保存的内容以及 printf
打印的默认精度。来自 man 3 printf
“如果缺少精度,则取为 6”。因此,当您使用 %lf
打印时(应该只是 %f
,因为 %f
已经是格式说明符对于 double
),您只能看到默认 6 位精度的 a
值。 (四舍五入)
a
在您调用 a = sqrt(i);
后不包含 2.645751
- 这只是默认精度输出你的 printf
语句。您可以通过为输出指定更长的精度来清楚地看到这一点,例如
printf("i = %d, a = %.10f\n", i, a);
输出:
i = 7, a = 2.6457513111
因此,您需要弄清楚实际 double
中包含的内容很可能不是您在使用带有默认 格式说明符的 printf
时看到的内容 和默认的精度。 double
值(64 位)表示 1 位
符号位、11 位
归一化指数和 52-位
尾数。并非所有数字都能够准确表示(只是由于表示每个可能数字的位数有限)。
一个很好但可以说读起来相当枯燥的引用文献是 What Every Programmer Should Know About Floating-Point
让我知道这是否有助于您的理解,或者您是否还有疑问。我们很乐意提供进一步的帮助。