C 中的泰勒级数逻辑

Taylor Series logic in C

我正在做一个项目,我们使用泰勒级数对 e^x 进行近似,其中 x 是用户输入的值。我们给出的测试值是 x=.5、x=1.0 和 x=1.5。目标是让输出应该是一个 table,在创建序列的循环的每次迭代中都有一行,第一列包含迭代次数,第二列是理论值(基于exp(x)),第三个求和的总和,第四个理论值与迭代值的差值

我目前的代码如下。就目前而言,随着代码的构建和运行,我的逻辑中存在一些漏洞,但输出不正确。如果我要解决我的问题,我认为我的求和不是从正确的位置 (1) 开始的,并且前两项是错误的 (1+x+(x^2/2!)+(x ^3/3!)...等).

与现有逻辑相比,我应该使用什么逻辑?谢谢

//cs 1325
// Dean Davis
// Dr. Paulk
// series convergence homework.

#include <stdio.h>
#include <float.h> // need it for FLT_EPSILON
#include <math.h>


unsigned long factorial(int); // function will calculate the factorial 

int main()
{
    int n = 0;
    unsigned long fact;  // this variable will hold the factorial value
    float x; // this will be the value read in from the user
    double theoval; // this will hold the theoretical value of e^x
    double holder; // will hold the value of the nth term
    double total = 0; // will accumulate the total summation
    double diff;  // will hold the sifferential between theoretical value and the summation
    puts("Please enter a numerical value greater than zero: "); // request input
    scanf_s("%f", &x); // read it in
    theoval=exp(x); // calc the theoretical value

    printf("# Iter      e^x       Sum       Diff\n");
    printf("-------   -------     -------   -------\n"); // set up the output

    while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
    {
        fact = factorial(n); // calls the factorial function
        holder = (pow(x, n)) / fact; // calculates the term n
        total = total + holder;  // adds to the sum
        diff = theoval - total;  // calc the diff
        printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
        if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
            continue;
        else
            n++;
    }

    printf("The number of iterations required for convergence is: %d\n", n); // out put this line

}


unsigned long factorial(int n)
{
    unsigned long int fact=n; 
    if (n == 0) // if n is zero, 0!=1
        return 1;
    else // so long as it is not, then we can calculate it like this
    {
        n--; // decrement it
        for (n; n > 0; n--)
        {
            fact = fact*n; // multiply the next number by the product of all the preceding terms
        }
        return fact;
    }
}

你的主要问题在这里:

    if ((theoval - total) >= FLT_EPSILON) // if it is smaller, then we don't wan't to increment n
        continue;
    else
        n++;

逻辑既倒退又不必要。它是倒退的,因为你避免在你想要递增它的那些情况下递增 n ,这是不必要的,因为在其他情况下你将退出循环,因为 while 表达式是假的。无条件递增n即可。

这表情也有点疑:

(theoval - total) >= FLT_EPSILON

FLT_EPSILON 与可表示 float 接近 1.0 之间的间距有关。不同地方的间距不同,因此将其用作绝对误差边界没有意义。由于泰勒级数以余数项的形式有明确定义的误差界限,我建议改为计算当前 n 的余数项的最大可能值,如果该边界误差值的比率存在则退出当前总和小于某个相当小的值,例如 0.00001.

除了 if ((theoval - total) >= FLT_EPSILON) 的问题外,您进行阶乘的方式也存在问题。这些价值很快就会变大。 13! = 6227020800 超出了 32 位 int 的范围,因此迭代次数超过 13 次就会得到无效结果。

您并不是真的想计算阶乘,而是想计算下一项。每一项都是前一项的 x / n 倍,因此您可以计算每一项而无需显式计算 x^nn!.

int n = 1;  // Start at 1 with the first term included so we don't divide by 0
double holder = 1; // will hold the value of the nth term
double total = 1;  // will accumulate the total summation
while ((theoval - total) >= FLT_EPSILON) //the loop to continue to sum the summation
{
    holder = holder * x / n;   // compute the next term from the last one
    total = total + term;  // adds to the sum
    printf(" %-9d%-12.6f%-14.6f%-10.8f\n", n, theoval, total, diff); // output it
    n++;
}