-1

我正在研究使用泰勒级数近似 e^x 的项目,其中 x 是用户输入的值。我们给出的测试值是 x=.5、x=1.0 和 x=1.5。目标是让输出应该是一个表,其中包含创建系列的循环的每次迭代的一行,第一列包含迭代次数,第二列是理论值(基于 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;
    }
}
4

2 回答 2

2

你的主要问题在这里:

    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

该宏与1.0 附近的可表示值FLT_EPSILON之间的间距有关。不同地方的间距不同,所以用它作为绝对误差界是没有意义的。由于泰勒级数有一个以余项形式定义好的误差界限,我建议改为计算当前余项的最大可能值,如果该界限误差值与当前总和的比率为小于某个合理的小值,例如 Maybe 。floatn0.00001

于 2015-07-23T00:58:21.743 回答
2

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

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

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++;
}
于 2015-07-23T01:56:23.877 回答