creating a Sin formula in the c programming language












0















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. 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;
}









share|improve this question

























  • Your power_func is not correct. It computes y^(2^x).

    – lurker
    Nov 20 '18 at 20:54













  • @lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

    – Amerov
    Nov 20 '18 at 20:58













  • See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

    – lurker
    Nov 20 '18 at 20:59













  • ohh mmm it's ok @lurker

    – Amerov
    Nov 20 '18 at 21:04








  • 1





    More specifically, y = y*y is a problem...

    – lurker
    Nov 20 '18 at 21:07
















0















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. 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;
}









share|improve this question

























  • Your power_func is not correct. It computes y^(2^x).

    – lurker
    Nov 20 '18 at 20:54













  • @lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

    – Amerov
    Nov 20 '18 at 20:58













  • See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

    – lurker
    Nov 20 '18 at 20:59













  • ohh mmm it's ok @lurker

    – Amerov
    Nov 20 '18 at 21:04








  • 1





    More specifically, y = y*y is a problem...

    – lurker
    Nov 20 '18 at 21:07














0












0








0








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. 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;
}









share|improve this question
















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. 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;
}






c visual-c++ sin






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 21:19







Amerov

















asked Nov 20 '18 at 20:51









AmerovAmerov

397




397













  • Your power_func is not correct. It computes y^(2^x).

    – lurker
    Nov 20 '18 at 20:54













  • @lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

    – Amerov
    Nov 20 '18 at 20:58













  • See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

    – lurker
    Nov 20 '18 at 20:59













  • ohh mmm it's ok @lurker

    – Amerov
    Nov 20 '18 at 21:04








  • 1





    More specifically, y = y*y is a problem...

    – lurker
    Nov 20 '18 at 21:07



















  • Your power_func is not correct. It computes y^(2^x).

    – lurker
    Nov 20 '18 at 20:54













  • @lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

    – Amerov
    Nov 20 '18 at 20:58













  • See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

    – lurker
    Nov 20 '18 at 20:59













  • ohh mmm it's ok @lurker

    – Amerov
    Nov 20 '18 at 21:04








  • 1





    More specifically, y = y*y is a problem...

    – lurker
    Nov 20 '18 at 21:07

















Your power_func is not correct. It computes y^(2^x).

– lurker
Nov 20 '18 at 20:54







Your power_func is not correct. It computes y^(2^x).

– lurker
Nov 20 '18 at 20:54















@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

– Amerov
Nov 20 '18 at 20:58







@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result

– Amerov
Nov 20 '18 at 20:58















See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

– lurker
Nov 20 '18 at 20:59







See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.

– lurker
Nov 20 '18 at 20:59















ohh mmm it's ok @lurker

– Amerov
Nov 20 '18 at 21:04







ohh mmm it's ok @lurker

– Amerov
Nov 20 '18 at 21:04






1




1





More specifically, y = y*y is a problem...

– lurker
Nov 20 '18 at 21:07





More specifically, y = y*y is a problem...

– lurker
Nov 20 '18 at 21:07












1 Answer
1






active

oldest

votes


















1














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). Use a double. Let's also write a function that emulates sin from <math.h>:



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. 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! = 479,001,600. A 64-bit int can hold 20! = 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. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.



Your power function should also have a double base. The exponent is integer. (But please use the more natural order power(base, exp).



Finally, (−1)^k is just an alternating sign. It is positive when k is even and odd otherwise.



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:



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%16gn", 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.)





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>.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401328%2fcreating-a-sin-formula-in-the-c-programming-language%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    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). Use a double. Let's also write a function that emulates sin from <math.h>:



    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. 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! = 479,001,600. A 64-bit int can hold 20! = 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. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.



    Your power function should also have a double base. The exponent is integer. (But please use the more natural order power(base, exp).



    Finally, (−1)^k is just an alternating sign. It is positive when k is even and odd otherwise.



    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:



    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%16gn", 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.)





    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>.






    share|improve this answer




























      1














      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). Use a double. Let's also write a function that emulates sin from <math.h>:



      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. 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! = 479,001,600. A 64-bit int can hold 20! = 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. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.



      Your power function should also have a double base. The exponent is integer. (But please use the more natural order power(base, exp).



      Finally, (−1)^k is just an alternating sign. It is positive when k is even and odd otherwise.



      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:



      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%16gn", 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.)





      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>.






      share|improve this answer


























        1












        1








        1







        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). Use a double. Let's also write a function that emulates sin from <math.h>:



        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. 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! = 479,001,600. A 64-bit int can hold 20! = 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. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.



        Your power function should also have a double base. The exponent is integer. (But please use the more natural order power(base, exp).



        Finally, (−1)^k is just an alternating sign. It is positive when k is even and odd otherwise.



        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:



        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%16gn", 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.)





        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>.






        share|improve this answer













        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). Use a double. Let's also write a function that emulates sin from <math.h>:



        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. 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! = 479,001,600. A 64-bit int can hold 20! = 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. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.



        Your power function should also have a double base. The exponent is integer. (But please use the more natural order power(base, exp).



        Finally, (−1)^k is just an alternating sign. It is positive when k is even and odd otherwise.



        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:



        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%16gn", 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.)





        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>.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 21 '18 at 10:00









        M OehmM Oehm

        21.4k31832




        21.4k31832






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401328%2fcreating-a-sin-formula-in-the-c-programming-language%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

            Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

            A Topological Invariant for $pi_3(U(n))$