如何在c中创建正弦函数

时间:2016-10-23 06:09:44

标签: c math

我知道他们在math.h中是一个sin函数但是我想自己创建这个函数,只是为了好玩。我已经基于正弦函数的Macluarin扩展创建了sin函数。 enter image description here

我写了幂函数和阶乘函数,它们从int main正常工作,但它们在sin函数中不起作用,这里是我的代码

int main()
{
    int i;
    double y;
    printf("\n\nPlease enter a value to find corresponding sin value\n");
    scanf("%d",&i);
    y=sin(i);
    printf("\nYour value is\n %f",y);
    return 0;
}

double sin(int z)
{
    int i=1;
    double value,val2,val3,sum=0;
    for(i=1;i<33;i+=2)
    {
        val2=power(z,i);
        val3=factorial(i);
        value=val2/val3;
        if(((i-1)/2)%2!=0){
            sum=sum-value;    //((power(x,i))/factorial(i));
        }else
        {
            sum=sum+value;
        }
    }
    printf("\n%f\n",sum);
    return sum;
}

int factorial(int x)
{
    int i,sum=1;
    for(i=1;i<=x;i++)
    {
        sum = sum*i;
    }
    return sum;
}

int power(int x,int y)
{
    unsigned long long int i,sum=1;
    for(i=1;i<=y;i++)
    {
        sum=sum*x;
    }
    return sum;
}

任何建议都会有所帮助。

4 个答案:

答案 0 :(得分:4)

公式需要以弧度为单位的值,但是你使用整数,所以我假设你给它度数。这将使公式给出错误的值。

此外,您使用int作为factorial()power()的返回值,这将导致溢出。如果您有32位机器,即使给出2,您的公式也会溢出,因为int只能达到2 ^ 31-1而您试图获得2 ^ 33。

此外,如果您的编译器没有抱怨您从unsigned long long int作为返回类型的函数返回int,请提高警告级别。

答案 1 :(得分:4)

int factorial()很快就溢出来了。 13!不适合32位整数。 21!不适合64位整数。

int power()似乎完全没了。为什么期望论证xint?顺便说一句,它也快速溢出。

计算McLauren系列的(几乎)正确的方法是表达下一个术语:

    term = (-1) * term * (x*x) / ((n+1)*(n+2));
    sum += term;
    n += 2;

它应该有效,但可能导致大x的数值不稳定。 Horner schedule是最终答案。

答案 2 :(得分:1)

正如其他人已经说过的那样,在他们自己的函数中计算powerfactorial部分是一个坏主意,因为它会溢出,即使是相当小的值。

您可以尝试将计算结合起来,以便每个循环中都有multiplicationdivide

像这样:

#include <stdio.h>

// This function returns the contribution from the k'th element
double kth_contribution(double x, int k)
{
    int i;
    int s = -1.0;
    double d = 1.0;
    if (k < 0) return 0;
    if (k == 1) return x;
    if (k % 2 == 0) return 0;
    if ((k-1) % 4 == 0) s = 1.0;

    for (i=1; i<=k; ++i)
    {
        d = d * x / i;
    }
    d = s * d;
    return d;
}

int main(void) {
    int k;
    int x = 1.0;
    for (k=0; k<33; ++k)
    {
        printf("k=%d: %0.80f\n", k, kth_contribution(1.0, k));
    }
    return 0;
}

输出:

k=0: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=1: 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=2: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=3: -0.16666666666666665741480812812369549646973609924316406250000000000000000000000000
k=4: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=5: 0.00833333333333333321768510160154619370587170124053955078125000000000000000000000
k=6: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=7: -0.00019841269841269841252631711547849135968135669827461242675781250000000000000000
k=8: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=9: 0.00000275573192239858925109505932704578867742384318262338638305664062500000000000
k=10: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=11: -0.00000002505210838544172022386617932135366437762513669440522789955139160156250000
k=12: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=13: 0.00000000016059043836821615925802332523156679827680548555690620560199022293090820
k=14: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=15: -0.00000000000076471637318198174152558028953378813433183758263567142421379685401917
k=16: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=17: 0.00000000000000281145725434552099254097088490189675684814327692728763707918915316

....

现在你只需要将所有贡献加在一起。

答案 3 :(得分:1)

如果你看一下像fdlibm那样的标准数学库,他们都会减少参数。 Macluarin系列最适合x的小值。因此,对于大x,您希望将x变为小范围。如果我们可以在-pi / 2和pi / 2之间找到y,使得x = y + 2 k pi,则以弧度工作。或者x = pi - y + 2 k pi。

这将有助于将y变为小范围,并且意味着您需要更少的系列术语来计算。