使用泰勒展开的正弦函数(C编程)

时间:2011-12-27 16:56:25

标签: c function sine

Here是个问题..

这是我到目前为止所做的,

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

long int factorial(int m)
{
    if (m==0 || m==1) return (1);
    else      return (m*factorial(m-1));
}
double power(double x,int n)
{
    double val=1;
    int i;
    for (i=1;i<=n;i++)
    {
        val*=x;
    }
    return val;
}

double sine(double x)
{
    int n;
    double val=0;
    for (n=0;n<8;n++)
    {
        double p = power(-1,n);
        double px = power(x,2*n+1);
        long fac = factorial(2*n+1);
        val += p * px / fac;
    }
    return val;
}

int main()
{
    double x;
    printf("Enter angles in degrees: ");
    scanf("%lf",&x);
    printf("\nValue of sine of %.2f is %.2lf\n",x,sine(x * M_PI / 180));
    printf("\nValue of sine of %.2f from library function is %.2lf\n",x,sin(x * M_PI / 180));
    return 0;
}

问题在于程序在0到180度之间完美地工作,但除此之外它会产生错误。当我将n中的for (n=0;n<8;n++)的值增加到8以上时,我会得到显着的错误..算法没有任何问题,我已经在我的计算器中进行了测试,程序似乎也没问题。我认为问题是由于数据类型的范围..我应该纠正什么摆脱这个错误?
感谢..

5 个答案:

答案 0 :(得分:2)

15!确实超出了32位整数可以容纳的范围。如果我是你,我会一直使用双打。

sin(x)的泰勒系列对于较大的x值收敛得更慢。对于x外-π,π。我加上/减去2 *π的倍数以获得尽可能小的x。

答案 1 :(得分:2)

错误是由数据类型的范围引起的。在sine()中,你计算的是15的阶乘,这是一个很大的数字,并且不适合32位(这可能是你的系统上实现的long int)。要解决此问题,您可以:

  1. 重新定义阶乘以返回双倍。
  2. 重新编写代码,将power和factorial组合成一个循环,交替乘以x,然后除以i。这将是看起来更混乱,但将避免溢出双倍的可能性(授予,我不认为这是你的用例的问题)。

答案 2 :(得分:0)

你可能遇到15问题!

我会打印出p,px,fac的值以及每次迭代的术语值,然后查看它们。

答案 3 :(得分:0)

你只在无限系列中包含8个术语。如果你在多项式方面考虑它一秒钟,你应该看到你没有足够的适合整个曲线。

事实是你只需要为0&lt; = x&lt; = \ pi;写函数;使用这些关系将遵循所有其他值:

  sin(-x) = -sin(x)

sin(x+\pi;) = -sin(x)

sin(x+2n\pi) = sin(x)

我建议您使用这些来标准化您的输入角度,以使您的功能适用于所有角度。

你的代码中内置了很多低效率(例如,你不断重新计算很容易适合表查找的阶乘;你使用power()来在-1和+1之间振荡)。但首先要让它正常工作,然后加快速度。

答案 4 :(得分:0)

您需要缩小范围。注意,泰勒级数最接近零,而在负范围内,它是正的范围的(负)镜像。因此,简而言之:缩小范围(通过2 PI的模块)将其包裹在您具有最高精度的范围内。超过1/2 PI的范围越来越不准确,所以你也想使用公式:sin(1/2 PI + x)= sin(1/2 PI - x)。对于负值,使用公式:sin(-x)= -sin(x)。现在,您只需要在跨越整个范围时评估0 - 1/2 PI的间隔。当然,对于非常大的值,2 PI的模块化精度将受到影响。