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

为何循环中变量值出现偏差?浮点精度与数组计算问题排查

浮点数精度偏差与数组越界问题分析

问题场景

这段C代码用于计算7个浮点项(仅展示tpos1和tpos2的计算逻辑),并从中筛选最小的正非零项。

核心计算代码

int hitb;
double PCLx = 2.936728;
double PCLz = -0.016691;
double PDCx = 0.102796;
double PDCz = 0.994702;
double q = 0.002344;
double s = 0.0266;
double v = 0.0744;
double a = -q * PDCx * PDCx;
double b = s * PDCx - 2 * q*PCLx*PDCx - PDCz;
double c = -1.0*(PCLz + q * pow(PCLx, 2) - s * PCLx + v);
double d = b * b - 4 * a*c;

if (d >= 0.0f) // 仅保留实数解
{
    tpos1 = (-b + sqrt(d)) / (2 * a);
    tpos2 = (-b - sqrt(d)) / (2 * a);
}

printf("\n %f %f %f %f %f %f %f", tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap);

运行输出

0.000000 0.000000 -40326.381162 -0.156221 -40105.748386 0.000194 0.016780

预期最小正非零项为tpos2=0.000194,但执行筛选循环后:

double smallest = -1.0;
double tlist[7] = { tcapneg, tcappos, tneg1, tneg2, tpos1, tpos2, tzcap };
const int size = sizeof(tlist) / sizeof(int);
for (int i = 0; i < size; i++)
{
    if (tlist[i] > EPSILON && (smallest == -1.0 || tlist[i] < smallest))
    {
        smallest = tlist[i];
    }
}
printf("\n %f", smallest);

输出的smallest值为0.000192,与tpos2的显示值不符,导致后续hitb赋值逻辑失败。


问题原因

  1. 数组长度计算错误
    代码中const int size = sizeof(tlist) / sizeof(int);是致命错误:tlist是double类型数组,sizeof(tlist)为7*8=56字节,sizeof(int)为4字节,计算后size=14,远大于实际的7个元素。循环会越界访问数组后的内存垃圾值,这些垃圾值可能是一个接近0.000192的正数,被错误选为最小值。

  2. 浮点数打印与实际存储的差异
    %f格式默认只保留6位小数,double类型实际存储的是更高精度的二进制浮点值。tpos2的真实值可能是0.000193xxxx,打印时四舍五入为0.000194,但参与比较的是未四舍五入的原始值;而筛选后打印的0.000192同样是垃圾值的四舍五入结果,并非tpos2本身。


修复方案

  • 修正数组长度计算:将sizeof(int)改为sizeof(double),或直接用sizeof(tlist[0]),即const int size = sizeof(tlist) / sizeof(tlist[0]);,确保循环仅遍历7个有效元素。
  • 精确查看浮点数:用%.10f等更高精度的格式打印,避免因四舍五入造成的视觉误解;浮点数比较时避免直接使用==,改用基于EPSILON的范围判断。

内容的提问来源于stack exchange,提问作者iontrap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:20:52