2

我用 C 语言编写了一个程序,它计算函数 exp(x) 在各种 x 值下的近似值,有些是正的,有些是负的。我的问题如下:

  1. 即使我之前能够在序列中包含 151 个术语,但现在即使在第 140 个术语中,该序列也会因 exp(100) 而爆炸。之后我把代码搞砸了,现在这个系列甚至在 130 学期就爆炸了​​。除此之外,我还使用 long double 作为数字格式,以允许计算和显示大的阶乘。如何解释这一现象?有时在连续执行代码后,我得到的结果接近于我从 Wolfram Alpha 检查的函数的实际值。
  2. 我听说“for”循环被证明是低效的。您是否考虑过“for”循环的替代方案?我很乐意尽可能多地实施它们。
  3. 我想以科学格式显示输出,但格式说明符(我不确定该术语)不允许我这样做。我在 printf 语句中使用的说明符是 %g。如何以科学格式显示输出?
  4. 根据我使用的硬件和软件,这是我可以获得的最大精度吗?
  5. 我还收到分段错误(核心转储)错误,而不是 x = -100 的显示。这背后的原因可能是什么?

感谢您的贡献。我感谢任何帮助和建议。

PS:我在 64 位硬件上使用 GCC 编译,但在 32 位 Ubuntu 12.04 LTS(又名 Precise Pangolin)上编译。

#include <stdio.h>
#include <math.h>
//We need to write a factorial function beforehand, since we
//have factorial in the denominators.
//Remembering that factorials are defined for integers; it is
//possible to define factorials of non-integer numbers using
//Gamma Function but we will omit that.
//We first declare the factorial function as follows:
long double factorial (double);
//Long long integer format only allows numbers in the order of 10^18 so 
//we shall use the sign bit in order to increase our range.
//Now we define it,
long double
factorial(double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
    int s = 1;
    long double pro = 1;
    if (n < 0)
        printf("Factorial is not defined for a negative number \n");
    else {
    while (n >= s) { 
    pro *= s;
    s++;
    }
    return pro;
    }
}

int main ()
{
    long double x[13] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -20, -50, -100};
//Here an array named "calc" is defined to store 
//the values of x.
//The upper index controls the accuracy of the Taylor Series, so
//it is suitable to make it an adjustable parameter. However, after
//a certain value of p the series become infinitely large to be 
//represented by the computer; hence we terminate the series at 
//the 151th term. 
int p = 150;
long double series[13][p];
int i, k;
//We only define the Taylor series for positive values of the exponent, and
//later we will use these values to calculate the reciprocals. This is done
//in this manner to avoid the ambiguity introduced into the sum due to terms
//alternating in sign.
long double sum[6] = { 0 };
for (i = 0; i <= 6;i++) {

        for (k = 0; k <= p; k++){
        series[i][k] = pow(x[i], k)/( factorial(k));
        sum[i] += series[i][k];
}
printf("Approximation for x = %Lf is %Lf \n", x[i], sum[i]);
}
//For negative numbers -taking into account first negative number is
//in the 8th position in the x array and still denoting the approximation
long double approx[5] = { 0 };
for (i = 7; i <= 12;i++) {
    approx[i - 7] = 1 / sum[i - 7];
    printf("Approximation for x = %Lf is %Lf \n", x[i], approx[i - 7]);
}
//printf("%Lf \n", factorial(3));
//The above line was introduced to test if the factorial function
//was functioning properly.
}
4

1 回答 1

2

回答你的一些问题。

1 我的 Eclipse 代码没有爆炸。

2 除了可能迭代次数过多之外,我认为使用 for 循环没有任何固有的低效率。

3"%Le"用于科学格式。

4 您可以获得的最大精度约为 LDBL_EPSILON in 1。取决于您的系统,我不知道(可能是功率的 1 部分(2,64))。请记住,精度是相对的,而不是绝对的。

5 分段错误可能是由于approx[5]. @Grijesh Chauhan

建议

添加-15long double x[13+1] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -15, -20, -50, -100 };. 更改各种其他13s。

添加返回错误条件:
if (n < 0) { printf("Factorial is not defined for a negative number \n"); return 0; }

改成long double approx[5+1+1] = { 0 };

添加返回到main().

如果你先把小项加起来,你会得到更好的数值结果。这通常意味着反转你的for (k = 0; k <= p; k++)循环。

int main() {
  long double x[13+1] = { 1, 5, 10, 15, 20, 50, 100, -1, -5, -10, -15, -20, -50, -100 };
  int p = 150;
  long double series[13+1][p];
  int i, k;

  long double sum[6+1] = { 0 };
  for (i = 0; i <= 6; i++) {
    for (k = 0; k <= p; k++) {
      series[i][k] = pow(x[i], k) / (factorial(k));
      sum[i] += series[i][k];
    }
    printf("Approximation for x = %Le is %Le %e\n", x[i], sum[i], exp(x[i]));
  }

  long double approx[7] = { 0 };
  for (i = 7; i <= 12; i++) {
    approx[i - 7] = 1 / sum[i - 7];
    printf("Approximation for x = %Le is %Le %e\n", x[i], approx[i - 7], exp(x[i]));
  }
  return 0;
}
于 2013-10-10T18:34:04.117 回答