You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何sqrt(7)赋值的浮点数相乘无精度损失?C语言技术咨询

为什么sqrt(7)的平方看起来没有精度损失?

这是个特别棒的问题,刚好摸到了浮点数精度和标准库函数细节的门道,咱们一步步拆解清楚:

核心真相:sqrt(7)的平方其实也有误差,只是被printf藏起来了

你看到的a * a = 7.000000并不是真的完全等于7,只是这个误差小到printf默认的6位小数输出格式无法显示。

double类型的浮点数有大约15-17位有效数字,sqrt(7)返回的是当前double能表示的、最接近真实√7的数值。这个数值的平方其实是一个非常非常接近7的数——比如实际计算出来可能是7.000000000000002,但当用%lf(默认保留6位小数)输出时,这个微小的误差被四舍五入掉了,就显示成了7.000000。

为什么直接赋值2.645751会出现明显的精度损失?

真实的√7大约是2.6457513110645906...,你直接赋值的2.645751只取了前6位小数,这个十进制数本身无法被精确转换成二进制浮点数(绝大多数十进制小数都不行)。

当你写a = 2.645751时,编译器会把它转换成最接近的double值,这个值其实是2.645750999999999...,它的平方和7的差距刚好大到在6位小数下能被看出来,于是就显示成了6.999998。

用更高精度的输出验证一下

你可以修改代码,把printf的输出精度调高到15位小数,就能看到真实的差异:

#include <stdio.h>
#include <math.h>
int main () {
    double a;
    int i;
    i = 7;
    a = sqrt(i);
    printf("i = %d, a = %.15lf\n", i, a);
    printf("a * a = %.15lf\n", a*a);
    a = 2.645751;
    printf("a = %.15lf\n", a);
    printf("a * a = %.15lf\n", a*a);
    return(0);
}

运行后会得到类似这样的结果:

i = 7, a = 2.645751311064591
a * a = 7.000000000000002
a = 2.645750999999999
a * a = 6.999998223001000

这下就能清楚看到:sqrt(7)的平方确实有微小误差,只是默认输出没显示;而直接赋值的数因为本身就是截断后的近似值,误差被放大了。

额外补充:标准库sqrt函数的优化

标准库的sqrt函数是经过专门优化的,它会返回在浮点数范围内最优的近似值,尽可能让这个值的平方接近原数。对于完全平方数(比如sqrt(4)),它会返回精确的2.0,平方后也完全等于4;但对于非完全平方数,还是会有微小的精度误差,只是通常被输出格式掩盖了。


内容的提问来源于stack exchange,提问作者Sleeping On a Giant's Shoulder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:46:55