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

Taylor级数(Maclaurin)计算sin(x)出现-nan问题求助

麦克劳林级数实现sin(x)时出现NaN的问题解决

我用麦克劳林级数实现sin(x)的计算公式:
$$\sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n x^{2n+1}}{(2n+1)!} = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots$$

当输入起始值1、结束值20、步长2时,控制台在x=9之后开始输出-nan:

  • x=9时,sin(x)=0.412118,泰勒级数结果为0.412118;
  • x=11时,sin(x)=-0.99999,泰勒级数结果为-0.999976;
  • x=13时,sin(x)=0.420167,泰勒级数结果为-nan。

需要解决这个问题用于实验作业,原实现代码如下:

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

int main(void) {
    float a, b, left, right, eps = 0.00001, step, x, add = 1, chis, znam, fact, sum = 0, delta;
    printf("Plese enter your start: ");
    scanf("%f", &a);
    printf("Your end: ");
    scanf("%f", &b);
    printf("and step: ");
    scanf("%f", &step);

    if (b < a || a < eps) {
        printf("Your inputs aren't correct");
        return -1;
    }

    printf("	X	           sin(x)	Taylor	   Delta\n");
    for (x = a; x < b; x += step) {

        printf("    x = %9f	", x);
        left = sin(x);
        printf("%9f", left);

        chis = -x;
        znam = 1;

        sum = 0;
        add = 1;
        fact = 1;
        while (fabs(add) > eps) {
            add = -1 * chis / znam;
            sum += add;
            chis *= -1 * (x * x);
            fact++;
            znam *= fact * (fact + 1);
            fact++;

        }
        printf("    %9f    ", sum);
        printf("%e\n", fabs(left - sum));
    }
}

问题原因分析

  1. 数值溢出:当x较大时,原代码中分母znam通过不断乘递增的阶乘项,float类型精度有限,会快速溢出到无穷大,后续计算chis/znam时就会产生NaN。
  2. 未利用三角函数周期性:sin(x)是周期为2π的函数,直接对大x值计算泰勒级数,级数项数值会急剧增大,不仅收敛慢,还极易触发数值溢出。
  3. 递推逻辑隐患:原代码的初始值设置和递推方式绕了弯路,小x值下能得到正确结果,但大x值下会加速数值溢出的发生。

解决方案及修正代码

核心优化点

  • 利用三角函数周期性,将x映射到[-π, π]区间,大幅降低计算时的x值;
  • 改用递推方式计算级数项,避免直接计算大数阶乘,减少溢出风险;
  • 替换float为double,提升数值计算的精度和抗溢出能力;
  • 修正循环条件和初始值,让逻辑更清晰合理。

修正后的代码

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

int main(void) {
    double a, b, left, eps = 1e-5, step, x, add, sum, delta;
    const double PI = acos(-1.0);

    printf("请输入起始值: ");
    scanf("%lf", &a);
    printf("请输入结束值: ");
    scanf("%lf", &b);
    printf("请输入步长: ");
    scanf("%lf", &step);

    if (b < a) {
        printf("输入参数不正确\n");
        return -1;
    }

    printf("      x           sin(x)        Taylor       Delta\n");
    for (x = a; x <= b; x += step) {
        // 将x映射到[-π, π]区间,利用sin的周期性
        double x_mod = fmod(x, 2 * PI);
        if (x_mod > PI) {
            x_mod -= 2 * PI;
        } else if (x_mod < -PI) {
            x_mod += 2 * PI;
        }

        printf("x = %9lf    ", x);
        left = sin(x);
        printf("%9lf", left);

        // 麦克劳林级数递推计算:首项为x_mod,后续项由前一项递推得到
        sum = x_mod;
        add = x_mod;
        int n = 1;
        while (fabs(add) > eps) {
            // 递推公式:第n+1项 = 第n项 * (-x²) / [(2n)(2n+1)]
            add *= -x_mod * x_mod / ((2 * n) * (2 * n + 1));
            sum += add;
            n++;
        }

        printf("    %9lf    ", sum);
        delta = fabs(left - sum);
        printf("%e\n", delta);
    }
    return 0;
}

效果验证

修正后的代码在输入起始值1、结束值20、步长2时,所有x值都能输出正确的泰勒级数结果,不会出现NaN,且计算精度符合设定的eps=1e-5要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:45:41