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

为何减小数值积分步长dx后,用float计算圆周率反而不准确?

为什么减小步长dx后,π的计算结果反而不准?

这问题的核心是单精度浮点数(float)的精度瓶颈,具体有三个关键点:

  • 累加误差爆炸:float只有6-7位十进制有效数字,没法精确表示0.000001这种小数。当dx改成1e-6后,循环要跑100万次,每次执行x += dx都会引入一点舍入误差。次数一多,x的实际值会严重偏离理论上的0 + n*dx,导致很多该计算的区间没被覆盖,或者计算位置错了,最终结果自然不准。
  • 大数吃小数:积分过程中,value会逐渐累积到接近π(约3.14),而每次要加的numerator/(1+x²)是个约4e-6的极小值。float的精度不足以在3.14这样的大数基础上精确加上这么小的数,很多次累加操作其实根本没改变value的值,等于白算了,结果自然偏小。
  • 误差抵消失效:理论上步长越小,矩形法的截断误差应该越小,但这里浮点数的舍入误差增长速度远超过截断误差的下降速度,总误差反而变大了。

修复方案

把代码里所有float换成double就行——double有15-17位有效数字,能轻松处理百万次累加的误差,也不会出现大数吃小数的问题。修改后的代码示例:

#include <iostream>

void fourOverX2(double& value, 
        const double lowerLimit, 
        const double upperLimit,
        const double dx)
{
    std::cout << "Values Sent: \n" 
    << lowerLimit << "\n" << upperLimit 
    << "\n" << dx << std::endl;

    value = 0;

    double x = lowerLimit, numerator = 4 * dx;

    while(x < upperLimit)
    {
        value += numerator / (1 + x * x);
        x += dx;
    }
}


int main()
{
    double value;

    fourOverX2(value, 0, 1, 0.000001);

    std::cout << "PI: " << value << std::endl;

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:01:18