C 为什么sqrt()分配的这个浮点数没有精度损失?

C 为什么sqrt()分配的这个浮点数没有精度损失?,c,precision,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

我想了解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);
}
#包括
#包括
int main()
{
双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);
返回(0);
}
以下是cc后的结果

i=7,a=2.645751

a*a=7.000000

a*a=6.999998

如果直接分配一个2.645751的浮点数,a*a的结果对我来说是可以理解的

但是,如果a被指定为sqrt(7),为什么a*a的输出没有精度损失


这对我来说很难理解

您指定的
a
为双精度,精度非常高,然后是您指定的硬编码精度。因此,硬编码数字的精度误差是可见的。同时,
sqrt()
的精度误差也不太明显,尽管在
printf()
您分配的
a
中,它并没有完全显示为具有非常长的精度的两倍,而您分配的精度是硬编码的。因此,硬编码数字的精度误差是可见的。同时,
sqrt()
的精度误差不是很明显,尽管它在
printf()
中没有完全显示出来,您的困惑来自
a
中实际包含的内容以及
printf
打印的默认精度。从
man 3 printf
“如果精度缺失,则取6”。因此,当您使用
%lf
打印时(应该是
%f
,因为
%f
已经是
双精度的格式说明符),您只能看到
a
的值达到默认的6位精度。(四舍五入)

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位
尾数。并不是所有的数字都能被精确地表示出来(只是由于表示每个可能的数字的位的限制)

一个好的,但可以说是相当枯燥的阅读,参考,深入到这一点是


让我知道这是否有助于您的理解,或者您是否还有问题。我们很乐意提供进一步帮助。

您的困惑来自于
a
中实际包含的内容以及
printf
打印的默认精度。从
man 3 printf
“如果精度缺失,则取6”。因此,当您使用
%lf
打印时(应该是
%f
,因为
%f
已经是
双精度的格式说明符),您只能看到
a
的值达到默认的6位精度。(四舍五入)

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位
尾数。并不是所有的数字都能被精确地表示出来(只是由于表示每个可能的数字的位的限制)

一个好的,但可以说是相当枯燥的阅读,参考,深入到这一点是


让我知道这是否有助于您的理解,或者您是否还有问题。我们很乐意提供进一步的帮助。

…您得到的结果是?….
double
有多少位精度?您正在打印多少个?可能重复您为什么不执行
printf(“i=%d,a=%.10f\n”,i,a)
并告诉我如果
a
仍然等于
2.645751
?为什么关闭标志?他对这种情况的理解是错误的,但对于一个学习者来说,这是一个相当合理的错误,因此在我的书中是一个很好的问题……你得到的结果是:……双精度有多少位数?您正在打印多少个?可能重复您为什么不执行
printf(“i=%d,a=%.10f\n”,i,a)
并告诉我如果
a
仍然等于
2.645751
?为什么关闭标志?他对这种情况的理解是错误的,但对于学习者来说,这是一个相当合理的错误,因此在我的书中是一个很好的问题。我将你的答案编辑为使用内联代码格式。我将你的答案编辑为使用内联代码格式。对于一般C问题,最好引用C标准,而不是POSIX/Unix/其他手册页。默认6位数字的引用可能是C 2011 7.21.6.18。这正是我试图解释的。请随意使用该措辞获得创作许可。(老板来了,我得帮忙买些杂货)@iBug,你知道,我只是个简单的人。我能做的就是读书
man 3 printf
声明
“f,f双参数四舍五入并转换