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

基于麦克劳林级数的自制C语言sin函数返回NaN问题排查

问题分析与修复方案

你的正弦函数实现返回NaN,核心是两个关键问题:

1. 大数计算触发数值溢出与无意义运算

直接用麦克劳林级数计算pow(doub, odd)/factorial(odd)时,当输入值(比如55)较大、迭代次数(100次)偏多:

  • pow(55, 201)会超出double的数值表示范围,变成无穷大(inf)
  • factorial(201)同样会突破double的精度上限,也变为无穷大
  • 无穷大除以无穷大的结果就是NaN(非数值)

另外你的factorial函数参数缺少类型声明(应写double factorial(int in)),虽不是NaN的直接原因,但会引发编译警告。

2. 未利用正弦函数的周期特性

麦克劳林级数仅在输入值接近0时收敛速度快,而55弧度远大于正弦函数的周期2π,直接计算会导致级数项先急剧膨胀再收缩,既低效又容易触发数值溢出。


修复后的代码

#include<stdio.h>
#include<math.h>

double sine(double x) {
    // 将输入值归约到[-π, π]范围,利用正弦的周期性
    x = fmod(x, 2 * M_PI);
    if (x > M_PI) {
        x -= 2 * M_PI;
    } else if (x < -M_PI) {
        x += 2 * M_PI;
    }

    double sum = x; // 级数第一项为x
    double term = x;
    int sign = -1;

    // 递推计算后续项,避免重复计算pow和阶乘
    for (int i = 1; i <= 20; i++) { // 20次迭代足够达到double精度
        int denominator = 2 * i * (2 * i + 1);
        term *= x * x / denominator;
        sum += sign * term;
        sign = -sign;
    }

    return sum;
}

int main() {
    printf("%lf\n", sine(55));
    // 可对比标准库结果:printf("%lf\n", sin(55));
    return 0;
}

核心优化点

  • 角度归约:通过fmod将输入映射到[-π, π],确保级数快速收敛,避免超大数计算
  • 递推计算:每一项基于前一项推导,完全抛弃pow和阶乘的重复计算,大幅提升数值稳定性
  • 精简迭代次数:归约后的输入只需20次左右迭代,就能达到double级别的精度,无需100次的冗余计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:25:21