1

This formula is from a friend of mine --- and I fixed it up for him. But I can't seem to figure out of how to get the right sine calculations per angle. Can someone please help me in getting the right commands in the sin part?

Code:

 #include<stdio.h>
#define PI 3.141592653589
#define NUMBER_OF_TERMS 10


double factorial(double x)
 {
  double counter, total;
  counter=x;
  total=x;
  while(counter>1)
  {
     counter--;
     total = total * counter;
  }
  return total;
  }
  double power(double x, double y)
  {
  double counter, j;
  counter=0;
  j = x;
  while (counter<(y-1))
  {
        counter++;
        x = x * j;
  }
  return x;
  }
  double cosine_func(double radians)
  {
  int counter, x;
  double cosine;
  x=0;
  counter=0;
  cosine = 0;
  while(counter<NUMBER_OF_TERMS-1)
  {
             counter++;
             x=x+2;
             if(counter%2 == 0)
              {
                  cosine = cosine - (power(radians, x)/factorial(x));
              }
             else if(counter%2 != 0)
             {
                  cosine = cosine + (power(radians, x)/factorial(x));
             }

  }
  return cosine;
  }
  double sine_func(double radians)
  {
  int counter, x;
  double sin;
  x=0;
  counter=0;
  sin = 0;
  while(counter<NUMBER_OF_TERMS-2)
  {
             counter++;
             x=x+3;
             if(counter%2 != 0)
              {
                  sin= sin -(power(radians, x)/factorial(x));
              }
             else if(counter%2 != 0)
             {
                sin= sin + (power(radians, x)/factorial(x));
             }
    }
  return sin;

    } 
   main()
 { 
  double counter;       
  double x_angles;         
  double x_radians;  
  double cosine;   
  double sin;      


  printf("11526769\n\n");
  printf("x(degrees)\t   x(radians)\t\t     cos x\t\t  sin x\t\t");
  counter = 0;
  x_angles = -185;
  while (x_angles<180)
  {
        counter++;
        x_angles+=5;
        x_radians=x_angles*PI/180.0;
        cosine=1-cosine_func(x_radians);
        sin=x_radians-sine_func(x_radians);
        printf("%.2lf\t\t%.12lf\t\t%.12lf\t\t%.12lf\n", x_angles, x_radians, cosine, sin);
  }
  return 0;
  } 
  • 3
    What is wrong with sin(-180) being 0.000000000528? You are working with floats and pi is an irrational number, so you kinda can't get extreme precision with calculations. You already have 9 decimals precision there for that value. – Sami Kuhmonen Oct 28 '15 at 08:51
  • You shouldn't have abandoned your previous attempt with loops for this tangle of variables. Instead you should have made it work and reused it. – molbdnilo Oct 28 '15 at 08:59
  • Suggest reversing computation - start with smallest fraction. E.g. http://stackoverflow.com/a/19958610/2410359 – chux - Reinstate Monica Oct 28 '15 at 13:27
  • Correction : sin x up to ten terms : x - x^3/3! + x^5/5! - x^7/7! and so on and so forth (pattern: exponent number + 2 = next factorial [ex: x = x^1 then 1 + 2 = 3 then next one : x^3/3!]) – Cassandra Nocturne Oct 29 '15 at 10:32
  • 1
    Please add or link the exact task description, any latin based language should be sufficient to divine the goals and imposed descriptions. At the moment it is an enigma what is expected of the code. – Lutz Lehmann Oct 29 '15 at 13:01
  • At least reduce the recursive computations to something like `p0=ang; p1=ang*ang*p0; p2=ang*ang*p1; p3=ang*ang*p2;... fac1=2*3; fac2 = 4*5*fac1; fac3=6*7*fac2;...`, this reduces the code length and could reduce the run time. – Lutz Lehmann Oct 29 '15 at 13:23
  • In your task description I see no demand that powers and factorials be explicitly present in the computation. Is there more to the restrictions than stdio.h and main()? – Lutz Lehmann Oct 29 '15 at 13:27
  • Well, that could work. Thanks for the advice, sweetie. But in what manner of the code? – Cassandra Nocturne Oct 29 '15 at 13:29
  • Well other restrictions include: * output of the program is a tabular list of values of the angles in both degrees and radian units, and the corresponding cosine and sine of the angles * no input *mathematical expressions  conditional control structure  counters  accumulators, and  loop control structure – Cassandra Nocturne Oct 29 '15 at 13:35
  • 1
    This still does not exclude any of the proposed solutions. – Lutz Lehmann Oct 29 '15 at 13:40
  • Well, that's one way to say that. I just need this to be solved quickly as possible so I can do the cosine code. – Cassandra Nocturne Oct 29 '15 at 13:48
  • Many answers consisting of minutes to hours go into answering the post. Adding additional restrictions, fundamentally changing the question is poor form. Better to review, learn and accept an answer. Then post another question with the additional restrictions. – chux - Reinstate Monica Oct 29 '15 at 13:48
  • @LutzL `p0 = angle_radians` `p1 = angle_radians * angle_radians * p0; ` `p2 = angle_radians* angle_radians * p1;` 'p3 = angle_radians* angle_radians * p2;` 'p4 = angle_radians* angle_radians * p3;` `p5 = angle_radians* angle_radians * p4; ` `p6 = angle_radians* angle_radians * p5;` `p7 = angle_radians* angle_radians * p6; ` `p8 = angle_radians* angle_radians * p7; ` `p9 = angle_radians* angle_radians * p8;` ` `p10 = angle_radians* angle_radians * p9;` – Cassandra Nocturne Oct 29 '15 at 13:54
  • @LutzL Not the mention the other one worked quite well. Thanks. – Cassandra Nocturne Oct 29 '15 at 13:58
  • printf("x(degrees)\t x(radians)\t\t sin x\t\t"); Also need help regarding this one ---- the results can't line up against the words. – Cassandra Nocturne Oct 29 '15 at 14:11
  • The most recent edit had nothing to do with the post - rolled back to most recent applicable post. – chux - Reinstate Monica Nov 06 '15 at 03:39

6 Answers6

0
for(f2=3;f2==1;f2--){
    fac2*=f2;
}

f2 is initialized with 3 and then in condition portion it is checked that if f2 is equaled to 1 which returns false.

This loop doesn't run for even a single time. Condition is false for the first time. So

fac2*=f2;

is never executed.

And you did same error for every next loop.

Mukit09
  • 2,956
  • 3
  • 24
  • 44
  • Thank you for pointing that out. Now it's : ' for(f1=1;f1==1;f1--){ ' ' fac1*=f1;' } for(f2=3;f2==1;f2--){ fac1*=f2; '}' 'for(f3=5;f3==1;f3--){' 'fac1*=f3;' '}' for(f4=7;f4==1;f4--){ fac1*=f4; } for(f5=9;f5==1;f5--){ fac1*=f5; } for(f6=11;f6==1;f6--){ fac1*=f6; } for(f7=13;f7==1;f7--){ fac1*=f7; } for(f8=15;f8==1;f8--){ fac1*=f8; } for(f9=17;f9==1;f9--){ fac1*=f9; } for(f10=19;f10==1;f10--){ fac1*=f10; }' – Cassandra Nocturne Oct 28 '15 at 09:13
  • Conditon portion of your ***for*** loop is wrong. Most probably, you wanted to write like this...f2>=1, f3>=1, .... , f10>=1. – Mukit09 Oct 28 '15 at 09:17
0

Most of your for loops never run. Check the correct syntax for them. Example:

for(f2=3;f2==1;f2--)

Is never executed because f2 = 3 and 3 != 1

Magisch
  • 7,312
  • 9
  • 36
  • 52
0
#include<stdio.h>
#define PI 3.141592653589
#define NUMBER_OF_TERMS 10

int
main()
{
 double angle_degrees, angle_radians;
 double sin, i, i2, i3, i4 , i5, i6, i7, i8, i9, i10;
 double fac1, fac2, fac3, fac4, fac5, fac6=1, fac7, fac8, fac9, fac10;
 double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10;
 double p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
 for(angle_degrees = -180; angle_degrees <= 180; angle_degrees += 5){
    p1 = angle_radians;
    p2 = angle_radians; 
    p3 = angle_radians;
    p4 = angle_radians;
    p5 = angle_radians;
    p6 = angle_radians; 
    p7 = angle_radians;
    p8 = angle_radians; 
    p9 = angle_radians;
    p10 = angle_radians;

    angle_radians = angle_degrees*PI/180;
    for(f1=3;f1>=1;f1--){
        fac1*=f1;
    }
    for(f2=5;f2>=1;f2--){
        fac1*=f2;
    }
    for(f3=7;f3>=1;f3--){
        fac1*=f3;
    }
    for(f4=9;f4>=1;f4--){
        fac1*=f4;
    }
    for(f5=11;f5>=1;f5--){
        fac1*=f5;
    }
    for(f6=13;f6>=1;f6--){
        fac1*=f6;
    }
    for(f7=15;f7>=1;f7--){
        fac1*=f7;
    }
    for(f8=17;f8>=1;f8--){
        fac1*=f8;
    }
    for(f9=19;f9>=1;f9--){
        fac1*=f9;
    }
    for(f10=21;f10>=1;f10--){
        fac1*=f10;
    }

    sin = angle_radians - (pow(p1, 3)/fac1) + (pow(p2, 5)/fac2) - (pow(p3, 7)/fac3) + (pow(p4, 9)/fac4) - (pow(p5, 11)/fac5) + (pow(p6, 13)/fac6) - (pow(p7, 15)/fac7) + (pow(p8, 17)/fac8) -(pow(p9, 19)/fac9) - (pow(p10, 21)/fac10);
    printf ("%.2lf\t\t%.12lf\t\t%.12lf\n", 
        angle_degrees, angle_radians, sin);
    }
 }

Here's a brand new one --- also I forgot these restrictions involved with it: 1)NO other function aside from main(). 2)NO inputs involved. 3) Angles = double data. 4)Output = angles (both degrees and radians), cosine (will work on that once done solving for sine), and sine.

0

The Taylor series of sin(x) is x-x^3/3!+x^5/5!-... . In your code I assume that p1 should mean x^1=x, p2=x^3, .. and f1=1! f2=3!, .. . Now in the result line you write

 sin = angle_radians - (p1/fac1) + (p2/fac2) + //...

which has the series with wrong sign + the first term again.

 sin = (p1/fac1) - (p2/fac2) + //...

Also the code is overly complicated. You can collect the result in a single loop:

double p=x;
double f=1;
double res=0;
int k=1;
for (int i=0;i<n;i++){
  res+=p/f;
  p*=-x*x;
  k+=2;
  f*=(k-1)*k;
}

Here x is the angle in radians p is the current power with right sign and f the factorial of the term.

As commented by LutzL this would overflow at some point because of the factorial. This version is safer against overflows

double res=0;
double term=x;
int k=1;
for (int i=0;i<n;i++){
  res+=term;
  k+=2;
  term*=-x*x/k/(k-1);
}
Ari Hietanen
  • 1,749
  • 13
  • 15
0

Code allowing for arbitrary number of terms

Copying myself from https://stackoverflow.com/a/28227419/3088138


Avoiding the recomputation of recursive functions like powers of the same argument and factorials is always a good idea. Thus a reduction to (a minimal amount of) elementary arithmetic operations looks like this:

public static double sine(int terms, double x) {
    double result = 1;
    double mxx = -x*x;
    double addens = 1;
    double temp = 2;
    for(int n = 2; n <= terms; n++) {
        addens *= mxx/temp++/temp++;
        result += addens; 
    }
    return x*result;

}

To study a production quality implementation, you can visit the math library libmath of the basic calculator bc, the gnu version can be read at http://code.metager.de/source/xref/gnu/bc/1.06/bc/libmath.b

It normalizes the argument wrt. pi and then uses the Taylor series of sin.


Horner-like schema for fixed number of terms

If you are restricted to a fixed number of terms in the power series, you can use a Horner like code for its evaluation. As example, take 4 terms, then

x-x^3/3!+x^5/5!-x^7/7! = x*(1-x²/6*(1-x²/20*(1-x²/42)))

This can be put into a loop

res = 1
for( k=num_terms; k-->1;) {
    res = 1-x*x*res/(2*k*(2*k+1))
}
res = res*x;

or you can unroll the loop

res = 1-x*x/42;
res = 1-x*x/20*res;
res = 1-x*x/6*res;
res = x*res;

You are free to combine x2=x*x or to rename x=angle_radians.

Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • That one's a good one, but I need a factorial in arithmetic form because of this restriction to my homework: I can't use any other function aside from main(). Also: can someone please tell me of how to put increments of 5 degrees? Don't have a clue on where to put that. – Cassandra Nocturne Oct 28 '15 at 13:53
  • Then please edit your question and add the exact text of your task description or provide a link to it. And please use the recursive nature of power and factorial, preferentially in one loop and without producing numerical overflow. -- Please describe why your outer loop is not working, it looks correct. – Lutz Lehmann Oct 28 '15 at 13:59
  • This one: `for(angle_degrees = -180; angle_degrees <= 180; angle_degrees += 5)`, it has the correct formulation and is at the right place. – Lutz Lehmann Oct 29 '15 at 12:56
0

Code can do better than sin(D2R(angle_degrees))

Step 1: Reduce angle to the range 0 to 90 degrees before converting to radians. Take advantage of the usual trig identities. Then we get exact answers for 90*n degrees.

Step 2: Calculate power series from last term up to the first as summing small terms first is more accurate.

#include<stdio.h>
#define PI 3.1415926535897932384626433832795
#define D2R(a) ((a)*PI/180)

#define NUMBER_OF_TERMS 10

int main(void) {
  double angle_degrees;
  for (angle_degrees = -360; angle_degrees <= 360; angle_degrees += 30) {
    double angle_radians = D2R(angle_degrees);
    int sign = 1;
    double angle_reduced_degrees = fmod(angle_degrees, 360.0);
    if (angle_reduced_degrees < 0) {
      angle_reduced_degrees = -angle_reduced_degrees;
      sign = -1;
    }
    int quadrant = (int) (angle_reduced_degrees / 90.0);
    angle_reduced_degrees -= quadrant * 90;
    switch (quadrant) {
      case 0:
        break;
      case 1:
        angle_reduced_degrees = 90 - angle_reduced_degrees;
        break;
      case 2:
        angle_reduced_degrees = -angle_reduced_degrees;
        sign = -sign;
        break;
      case 3:
        angle_reduced_degrees = 90 - angle_reduced_degrees;
        sign = -sign;
        break;
    }
    double angle_reduced_radians = D2R(angle_reduced_degrees);

    long long denom = 1;
    for (int i = 1; i < NUMBER_OF_TERMS; i++) {
      denom *= -(2 * i + 0) * (2 * i + 1);
    }
    double aa = angle_reduced_radians * angle_reduced_radians;
    double sum = 0;
    for (int i = NUMBER_OF_TERMS; --i >= 0;) {
      double term = 1.0 / (double) denom;
      sum = term + sum * aa;
      if (i) denom /= (-(2 * i) * (2 * i + 1));
    }

    sum *= angle_reduced_radians * sign;
    sum *= 1.0; // to get rid of -0.0
    printf("sine(%+7.2f degrees %+9f radians) = %+20.17f sin()=%+20.17f\n",
            angle_degrees, angle_radians, sum, sin(angle_radians));
  }
  return 0;
}

Output

//                                        This code            math.h sin()
sine(-360.00 degrees -6.283185 radians) = -0.00000000000000000 sin()=+0.00000000000000024
sine(-330.00 degrees -5.759587 radians) = +0.50000000000000000 sin()=+0.49999999999999967
sine(-300.00 degrees -5.235988 radians) = +0.86602540378443871 sin()=+0.86602540378443860
sine(-270.00 degrees -4.712389 radians) = +0.99999999999999989 sin()=+1.00000000000000000
sine(-240.00 degrees -4.188790 radians) = -0.86602540378443871 sin()=+0.86602540378443882
sine(-210.00 degrees -3.665191 radians) = -0.50000000000000000 sin()=+0.50000000000000011
sine(-180.00 degrees -3.141593 radians) = -0.00000000000000000 sin()=-0.00000000000000012
sine(-150.00 degrees -2.617994 radians) = -0.50000000000000000 sin()=-0.49999999999999994
sine(-120.00 degrees -2.094395 radians) = -0.86602540378443871 sin()=-0.86602540378443860
sine( -90.00 degrees -1.570796 radians) = -0.99999999999999989 sin()=-1.00000000000000000
sine( -60.00 degrees -1.047198 radians) = -0.86602540378443871 sin()=-0.86602540378443871
sine( -30.00 degrees -0.523599 radians) = -0.50000000000000000 sin()=-0.50000000000000000
sine(  +0.00 degrees +0.000000 radians) = +0.00000000000000000 sin()=+0.00000000000000000
sine( +30.00 degrees +0.523599 radians) = +0.50000000000000000 sin()=+0.50000000000000000
sine( +60.00 degrees +1.047198 radians) = +0.86602540378443871 sin()=+0.86602540378443871
sine( +90.00 degrees +1.570796 radians) = +0.99999999999999989 sin()=+1.00000000000000000
sine(+120.00 degrees +2.094395 radians) = +0.86602540378443871 sin()=+0.86602540378443860
sine(+150.00 degrees +2.617994 radians) = +0.50000000000000000 sin()=+0.49999999999999994
sine(+180.00 degrees +3.141593 radians) = +0.00000000000000000 sin()=+0.00000000000000012
sine(+210.00 degrees +3.665191 radians) = +0.50000000000000000 sin()=-0.50000000000000011
sine(+240.00 degrees +4.188790 radians) = +0.86602540378443871 sin()=-0.86602540378443882
sine(+270.00 degrees +4.712389 radians) = -0.99999999999999989 sin()=-1.00000000000000000
sine(+300.00 degrees +5.235988 radians) = -0.86602540378443871 sin()=-0.86602540378443860
sine(+330.00 degrees +5.759587 radians) = -0.50000000000000000 sin()=-0.49999999999999967
sine(+360.00 degrees +6.283185 radians) = +0.00000000000000000 sin()=-0.00000000000000024

Some minor improvements could be made.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • That could work---thanks, but that's not the one I am looking for. – Cassandra Nocturne Oct 29 '15 at 10:18
  • You can reduce the work for the angle reduction slightly if you add after `angdeg=fmod(angdeg,360)` the additional reduction `angdeg=fmod(angdeg+360+180,360)-180`, after that the angle should be in the range `-180..180`. – Lutz Lehmann Oct 29 '15 at 13:17
  • @LutzL Calling `fmod(angdeg,360)` first has the advantage of not introducing _any_ precision loss. (http://stackoverflow.com/q/20928253/2410359) unlike `angdeg+360+180`. The answer's angle reduction are crafted to not have _any_ precision loss until `angle_reduced_radians = D2R(angle_reduced_degrees)` It is steps like that that keep `sine(x) == sine(x+360.0*n)` unlike `sin(D2R(x+360.0*n))`. – chux - Reinstate Monica Oct 29 '15 at 13:28
  • I did say to use both. That is needed since usually the quotient computation in all mod implementations rounds towards 0. Thus the first fmod leaves values between -360..360. Now there are multiple possibilities to reduce this to only one period. – Lutz Lehmann Oct 29 '15 at 13:32
  • @LutzL (I now see the implied both) True that `angdeg=fmod(angdeg+360+180,360)-180` after `angdeg=fmod(angdeg,360)` reduces things to 1 period [-180...180) albeit with 1 bit precision loss. This answer uses `if (angle_reduced_degrees < 0)` after `angdeg=fmod(angdeg,360)` to reduce to 1 period. [0...360) without precision loss. – chux - Reinstate Monica Oct 29 '15 at 13:39