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

Python浮点数乘法误差疑问:float64累积误差,float32无累积?求C等效代码

浮点数迭代行为差异解析及C语言复现

现象原因

数学上,迭代式 c = 3a - 2b 当初始 a = b = 0.1 时,理论上每次迭代都应得到 c = 0.1,但由于0.1无法精确表示为二进制浮点数,不同精度的浮点数会表现出截然不同的行为:

float32(单精度)无误差累积

0.1在float32中的近似存储值为 0.10000000149011612。计算 3*a - 2*b 时:

  • 即便计算过程被临时提升到更高精度(如double),最终结果恰好等于float32中0.1的近似值;
  • 赋值回float32类型变量时,无需额外舍入,因此每次迭代后a和b始终保持初始值不变。

float64(双精度)误差累积发散

0.1在float64中的近似值为 0.10000000000000000555...,计算3*a - 2*b后得到的结果是0.1000000000000000333...,与初始值存在微小偏差。由于双精度计算没有精度截断,每次迭代的偏差会被持续累积,经过100次迭代后值会迅速膨胀到极大值。

C语言复现代码

复现float32不变行为

使用float类型,确保计算结果截断回单精度:

#include <stdio.h>

int main() {
    const int N = 100;
    float a = 0.1f;
    float b = 0.1f;

    for (int i = 0; i < N; ++i) {
        const float c = 3*a - 2*b;
        b = a;
        a = c;
    }
    // 用%.16f可以看到精确的单精度值
    printf("float结果:%.16f\n", a);
    return 0;
}

输出:float结果:0.1000000014901161

复现float64发散行为

使用double类型,复现误差累积:

#include <stdio.h>

int main() {
    const int N = 100;
    double a = 0.1;
    double b = 0.1;

    for (int i = 0; i < N; ++i) {
        const double c = 3*a - 2*b;
        b = a;
        a = c;
    }
    printf("double结果:%.2lf\n", a);
    return 0;
}

输出:double结果:35184372088832.07(与Python中numpy.float64的结果一致)

无法复现float32行为的常见原因

  • 误用double类型而非float;
  • 编译器优化导致计算精度被提升后未截断回单精度,可尝试添加编译选项-ffloat-store(GCC)强制将浮点值存储回变量,确保截断到单精度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:40:22