简体   繁体   English

用C编程语言创建一个Sin公式

[英]creating a Sin formula in the c programming language

Hello everyone I'm trying to implement a programm like the fomular sin The program will compile but when running it i am not getting the correct values back from my inputs. 大家好,我正在尝试实现像fomular sin这样的程序。该程序可以编译,但是运行时,我没有从输入中获得正确的值。 I'm still getting a negativ value. 我仍然获得负面价值。 can someone help me please ? 有人能帮助我吗 ? I had a look at the other posts but that didn't help me :(. my code is: 我看了其他帖子,但这对我没有帮助:(。我的代码是:

#include <stdio.h>
#include <stdlib.h>

int fac (int a) { // fac. => factorial and i is for the loop

    int i,fac;
        fac=1;

    for (i=1; i<=a; i++){
        fac=fac*i;
    }
    return fac;
}
int power_func(int x,int y) // x is exponent and y is the number that would be multiplied by itself.
     {
         int i;//i is for the loop
         int ret = 1;
         for(i=1;i<=x;i++)
         {
             ret *= y;
         }
         return ret;
     }
int main()
{
    int num,denom,i;//num. is numerator and denom. is denominator
    int sin,x,result=0;
    printf("Enter the number of x \n");
    scanf("%d",&x);
    for(i=0;i<x;i++)
    {

    num= power_func(2*i+1,x);
    denom=fac((2*i+1));
    sin=power_func(i,-1)*num/denom;
    result =result+sin;
    printf("%d \n",result);
    }

    return 0;
}

You have various misconceptions about your code. 您对代码有各种误解。 First, let's look at the formula you have provided: 首先,让我们看一下您提供的公式:

sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)!   for x ∈ R;   k = 0, ..., infinity

The sine function takes a real and returns a real. 正弦函数采用实数并返回实数。 Therefore, you should use a floating-point type for x and sin(x). 因此,应该对x和sin(x)使用浮点类型。 Use a double . 使用double Let's also write a function that emulates sin from <math.h> : 让我们还编写一个函数来模拟<math.h> sin

double my_sin(double x);

The above series is accurate when there are infinitely many terms. 当存在无限多个术语时,以上系列是准确的。 We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double . 当然,我们不能计算出那么多,这也将浪费时间,因为术语越来越小,直到不能再用double表示为止。 So let's chose a maximum number of terms, say 因此,让我们选择最大数量的术语

enum {
    nTerms = 8
};

Factorials grow big fast. 阶乘迅速增长。 A regular 32-bit int can hold 12! 常规的32位int可以容纳12个! = 479,001,600. = 479,001,600。 A 64-bit int can hold 20! 一个64位的int可以容纳20个! = 2,432,902,008,176,640,000. = 2,432,902,008,176,640,000。 Since we are going to use these factorials in a double calculation, we can just as well use double here. 由于我们将在double精度计算中使用这些阶乘,因此我们也可以在此处使用double精度。 That will even allow us to represent 22! 这甚至可以使我们代表22! = 1,124,000,727,777,607,680,000 accurately. =准确地为1,124,000,727,777,607,680,000。

Your power function should also have a double base. 您的幂函数还应该具有double底数。 The exponent is integer. 指数是整数。 (But please use the more natural order power(base, exp) . (但是请使用更自然的阶power(base, exp)

Finally, (−1)^k is just an alternating sign. 最后, (−1)^k只是一个交替符号。 It is positive when k is even and odd otherwise. k为偶数时为正,否则为奇数。

Putting all this together: 将所有这些放在一起:

double fact(int n)
{
    double result = 1.0;

    while (n > 0) {
        result *= n;
        n--;
    }

    return result;
}

double power(double a, int n)
{
    double result = 1.0;

    while (n > 0) {
        result *= a;
        n--;
    }

    return result;
}

enum {
    nTerms = 8
};

double my_sin(double x)
{
    double result = 0.0;
    double sign = 1.0;

    for(int k = 0; k < nTerms; k++)
    {
        double num = power(x, 2*k + 1);
        double denom = fact(2*k + 1);
        double term = sign * num / denom;

        result = result + term;
        sign = -sign;
    }

    return result;
}

If we write a driver program to print out some test values and compare them with the standard math library's implementation of sin : 如果我们编写驱动程序以打印一些测试值,并将它们与标准数学库中sin的实现进行比较:

int main(void)
{
    for (int i = 0; i < 15; i++) {
        double x = 0.1 * i;
        double m = my_sin(x);       // series approximation
        double s = sin(x);          // <math.h> implementation

        printf("%16g%16g%16g%16g\n", x, m, s, m - s);
    }

    return 0;
}

we can see that we're not doing so badly: 我们可以看到我们做得还不错:

           x       my_sin(x)          sin(x)      difference
    --------    ------------    ------------    ------------
           0               0               0               0
         0.1       0.0998334       0.0998334     1.38778e-17
         0.2        0.198669        0.198669     2.77556e-17
         0.3         0.29552         0.29552               0
         0.4        0.389418        0.389418    -5.55112e-17
         0.5        0.479426        0.479426               0
         0.6        0.564642        0.564642               0
         0.7        0.644218        0.644218               0
         0.8        0.717356        0.717356               0
         0.9        0.783327        0.783327    -4.44089e-16
           1        0.841471        0.841471    -2.77556e-15
         1.1        0.891207        0.891207    -1.43219e-14
         1.2        0.932039        0.932039    -6.20615e-14
         1.3        0.963558        0.963558    -2.42029e-13
         1.4         0.98545         0.98545    -8.52318e-13

(But it gets worse the farther we go from zero. Try other values for nTerms .) (但是,我们离零越远,情况就nTerms 。为nTerms尝试其他值。)


I've said in a comment above that you don't need to calculate factorials and powers and that's true. 我在上面的评论中说过,您不需要计算阶乘和功效,这是事实。 If you look at the terms of the series, you will see that: 如果查看该系列的条款,您将看到:

s[n] = -1 * s[n - 1] * x^2 / (2*n * (2*n +1))

s[0] = x
s[1] = x^3 / (1 * 2 * 3)         =                 x * x^2 / (2 * 3)
s[2] = x^5 / (1 * 2 * 3 * 4 * 5) = x^3 / (1 * 2 * 3) * x^2 / (4 * 5)
s[3] = ...

Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small: 这是一个实现该功能的函数,它将计算项直到将它们加到总和之前都不会改变它,因为它们太小了:

double sin_r(double x)
{
    double sum = x;
    double a = x;
    int n;

    for (n = 1; ; n++) {
        double was = sum;

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

        if (was == sum) break;
    }

    return sum;
}

The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. 通过首先对第一项求和,加法仍然会失去一些精度,但是它的好处是不必计算阶乘和幂。 You don't even need <math.h> . 您甚至不需要<math.h>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM