February 13th, 2007, 06:31 AM

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(num1.0) );
}
February 13th, 2007, 07:53 AM

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(num1.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 07:57 AM.
February 13th, 2007, 07:55 AM

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_totaltotal) < 0.0001 )
You're dealing with approximate numbers, so you need an approximate test for equality.
February 13th, 2007, 07:56 AM

lol more noob at this than I thought!
Just tested more and it doesn't work, sry :o
February 13th, 2007, 08:12 AM

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.7557319223985890652557319223986e7
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)
The only Verdict is Vengeance a Vendetta held as a Votive, not in Vain, for the Value and Veracity of such shall one day Vindicate the Vigilant and the Virtuous
Mav RLZ AC/DC RLZ
February 13th, 2007, 09:22 AM

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.
February 13th, 2007, 11:47 AM

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
February 13th, 2007, 12:11 PM

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 floatingpoint 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 smallmagnitude term to a largemagnitude sum.
Last edited by dwise1_aol; February 13th, 2007 at 12:19 PM.
February 13th, 2007, 12:54 PM

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.
The only Verdict is Vengeance a Vendetta held as a Votive, not in Vain, for the Value and Veracity of such shall one day Vindicate the Vigilant and the Virtuous
Mav RLZ AC/DC RLZ
February 14th, 2007, 04:26 AM

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 80bit 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.
February 14th, 2007, 01:16 PM

> 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.
February 14th, 2007, 03:17 PM

It was just a lucky guess Salem  I'm just a "moron" :D