为什么sqrt()指定的浮点数没有精度损失?

Sle*_*der 0 c precision

我想了解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的输出没有精度损失?

这对我来说很难理解.

Dav*_*ica 6

您的困惑来自于实际存在的内容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尾数.并非所有数字都能够被准确表示(仅仅由于比特的限制来表示每个可能的数字).

一个好的,但可以说是相当干燥的阅读,进一步深入探讨了每个程序员应该知道的关于浮点的内容

如果这有助于您的理解,或者您是否还有疑问,请告诉我.我们很乐意进一步提供帮助.