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