### Thread: A program to calculate sine(x) (C)

1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Aug 2006
Posts
24
Rep Power
0

#### A program to calculate sine(x) (C)

Hello everyone, I am trying to calculate the sine of a number using taylor series.....and sth is wrong with this program.
It has an inf loop.
I think it has to do with the float or sth...
I calculate the terms, until the previous term is equal to the current term...and it dont gets out of the loop....
Any ideas ?? Thx in Advance.

Code:
```/****************************************************************************
*           																*
*	Sine(x)= x - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) .......				*
*  																		*
*  																		*
*																			*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

float fact( float num);

main() {
float number,total,new_total;
float result,top,bottom;
float sign=1.0,exp=1.0;

printf("Give a number: ");
scanf("%f",&number);
result=number;
total=number;

for (;;) {
sign=-sign;
exp+=2.0;
top=sign*pow(number,exp);
bottom=fact(exp);
new_total=top/bottom;
if (new_total==total)
break;
total=new_total;
result+=total;
}

printf("Sine of %f=%f\n",number,result);

}

float fact( float num) {
if (num<=1.0)
return(1.0);
else
return(num * fact(num-1.0) );
}```
2. I think you're right about it being float.
I'm not too up on C++ (just learning at the monment) but I'm guessing that float isn't big enough to hold the Taylor expansion.
If you change it to double it appears to work fine
c++ Code:
```
/****************************************************************************
*           																*
*	Sine(x)= x - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) .......				*
*  																		*
*  																		*
*																			*
****************************************************************************/
#include <stdio.h>
#include <cstdlib>
#include <math.h>
#include <iostream>

using namespace std;

double fact( double num);

main() {
double number,total,new_total;
double result,top,bottom;
double sign=1.0,exp=1.0;

printf("Give a number: ");
//	scanf("%f",&number);
cin>>number;
result=number;
total=number;

for (;;) {
sign=-sign;
exp+=2.0;
top=sign*pow(number,exp);
bottom=fact(exp);
new_total=top/bottom;
if (new_total==total)
break;
total=new_total;
result+=total;
}

printf("Sine of %f=%f\n",number,result);

}

double fact( double num) {
if (num<=1.0)
return(1.0);
else
return(num * fact(num-1.0) );
}```

I've added line 11, 12, 14 and 25.
I used cin as I'm not sure how to make scanf read in a double type (I said I was a noob 2 this :))
Not fully tested it, but it seems to work

EDIT: DOESN'T WORK :o
Last edited by geo_101; February 13th, 2007 at 06:57 AM.
3. You can't compare floats for equality.
http://en.wikipedia.org/wiki/Floating_point
In particular, read the link to David Goldberg's paper at the end.

> if (new_total==total)
Needs to be something like
if ( fabs(new_total-total) < 0.0001 )
You're dealing with approximate numbers, so you need an approximate test for equality.
4. lol more noob at this than I thought!
Just tested more and it doesn't work, sry :o
5. Well you could change your teminating condition! and that depends on how accurate you want the result to be, my guess is for sin(x);
computing beyond n = 5 (the fifth expression is futile ), this is mainlybecause your remainder is a factorial term (which is exponential ) so what happens is the fraction becomes so small that it contributes to the real number (the value of sin(x) ) very far away from the deciaml place!

e.g. 1/(10!) = 2.7557319223985890652557319223986e-7
that .000000275555...

and the numerator is obviously in radians!
using series expansion till the third element ( till 5!)
sin(Pi/4) = .70687 which is very close to sin (45) = 1/sqrt(2);
So in the End how accurate do you want it to be ?
p.s Pi/4 for radians ( Pi = 3.14)
6. Wow, brings back memories. I remember programming what I think was taylor series into my casio graphing calculator in high school so I could check my work on tests (note: not actually do the work, just check it), and programming it in fortran in college for a numerical computing class.
7. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Aug 2006
Posts
24
Rep Power
0
Thx a lot dudes.....
How accurate.. ?? Lets say accurate enough to compare it with a casio fx series hand calculator.

Well i am wandering if i write the above program in perl what the results would be. (lets check it out)

Thx
8. How accurate? Well, the series converges because eventually the terms become vanishingly small. So figure how accurate you want it and test for when the new term is smaller than that.

However, because of the inherent limitations of the floating-point representation you will need to choose a test value that can still be represented by a double.

But also, wouldn't Horner's Rule come into play? It's been nearly three decades so I might not remember correctly, but if you're summing a polynomial (which is basically what a series is, IIRC) then you need to start with the smallest terms first. If you instead start with the largest terms, then when you add the smallest terms it would be as if you were adding zero.

This would mean that in choosing the smallest term that you could add that you would need to consider the mantissa more closely than the exponent. Unless you can figure out a way to use Horner's Rule.

PS
OK, I didn't quite remember correctly (http://en.wikipedia.org/wiki/Horner%27s_rule).

However, there is still the issue of trying to add a small-magnitude term to a large-magnitude sum.
Last edited by dwise1_aol; February 13th, 2007 at 11:19 AM.
9. Originally Posted by Linuxlover0101
Thx a lot dudes.....
How accurate.. ?? Lets say accurate enough to compare it with a casio fx series hand calculator.

Well i am wandering if i write the above program in perl what the results would be. (lets check it out)

Thx
well I have a 991 MS and that is one of the latermodels I think, and it has precision till nine decimal places !

and one point to think ...
1/3 = .333333333333
1/5 = .2

so instead of fixing on number of decimal places, I would suggest you limit your accuracy based on the number of interations, and then round up to how many decimal places u want!

And like I said before
sin(Pi/4) = .706861317 till the third term in the series ( that is till 5! ) which is very close to 1/sqrt(2) = .707106781,
In other words the former is accurate till the fourth decimal place ( if you round it up mathematically)

So just experiment with the number of iterations till you get the level of accuracy you require.
10. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2006
Posts
271
Rep Power
15
As mentioned previously, comparing floating point numbers for equality is a bad idea.

If you have an IEEE 754 compliant system, the compiler is very likely defaulting the internal precision control of the math unit to the 80-bit temp real format, but your memory format is the 32 bit short real - IOW bits get lost on a memory store out of the FP unit for both floats and doubles and stay lost forever.
11. > IOW bits get lost on a memory store out of the FP unit for both floats and doubles and stay lost forever.
Absolutely!
Some time ago, this thread on another board was about that very issue.
Changing the code changed the ability of the compiler to keep values in floating point registers (and thus changed the result).

It took 20 replies to finally convince them that there was really a problem with comparing floats for equality.
12. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2006
Posts
271
Rep Power
15
It was just a lucky guess Salem - I'm just a "moron" :D