我想了解C如何处理浮点数的精度损失.
这是我的简单代码:
#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);
}
Run Code Online (Sandbox Code Playgroud)
以下是cc之后的结果
i = 7,a = 2.645751
a*a = 7.000000
a*a = 6.999998
如果直接分配一个2.645751的浮点数,a*a的结果对我来说是可以理解的.
但是如果a被分配了sqrt(7),为什么a*a的输出没有精度损失?
这对我来说很难理解.
您的困惑来自于实际存在的内容a和打印的默认精度printf.从man 3 printf "如果缺少精度,它被视为6".因此,当您使用打印%lf(这应该是简单地%f作为%f已经是格式说明的double),你只看到价值a为默认的6位精度.(四舍五入)
a不包含2.645751您的调用a = sqrt(i);- 这只是您的printf语句的默认精度输出.您可以通过为输出指定更长的精度来清楚地看到这一点,例如
printf("i = %d, a = %.10f\n", i, a);
Run Code Online (Sandbox Code Playgroud)
输出:
i = 7, a = 2.6457513111
Run Code Online (Sandbox Code Playgroud)
因此,您需要清楚地了解实际中包含的double内容很可能不是您在使用printf默认格式说明符和默认精度时所看到的内容.double值(64位)表示1-bit符号位,11-bit归一化指数和52-bit尾数.并非所有数字都能够被准确表示(仅仅由于比特的限制来表示每个可能的数字).
一个好的,但可以说是相当干燥的阅读,进一步深入探讨了每个程序员应该知道的关于浮点的内容
如果这有助于您的理解,或者您是否还有疑问,请告诉我.我们很乐意进一步提供帮助.