Reputation: 282
So, I'm trying to create a program that calculates cos(x) by using a Taylor approximation.
The program is really simple: The user inputs a parameter x (x being an angle in radians) and a float ε, which is the precision of the value of cos(x).
Basically, the only thing the program has to do is to calculate this sum: x^0/0! - x^2/2! + x^4/4! - x^6! + x^8/8! - ..., until the terms are smaller than ε, that is, the value for cos(x) it'll be within our range of precision.
So, here's the code:
#include <stdio.h>
/* Calculates cos(x) by using a Taylor approximation:
cos(x) = x^0/(0!) - x^2/(2!) + x^4/(4!) - x^6/(6!) + x^8/(8!) - ... */
int main(void)
{
int k; // dummy variable k
float x, // parameter of cos(x), in radians
epsilon; // precision of cos(x) (cos = sum ± epsilon)
sum, // sum of the terms of the polynomial series
term; // variable that stores each term of the summation
scanf("%f %f", &x, &epsilon);
sum = term = 1, k = 0;
while (term >= epsilon && -term <= epsilon)
// while abs(term) is smaller than epsilon
{
k += 2;
term *= -(x*x)/(k*(k-1));
sum += term;
}
printf("cos(%f) = %f\n", x, sum);
return 0;
}
At first, I tried to solve it by calculating the factorials on a separate variable "fact", though that caused an overflow even with reasonable large values for ε.
To solve this, I noticed that I could just multiply the previous term by -x² / (k(k - 1)), increasing k by 2 in every iteration, to get the next term. I thought that would solve my problem, but then again, it is not working.
The program compiles fine, but for example, if I input:
3.141593 0.001
The output is:
cos(3.141593) = -3.934803
...and that is obviously wrong. Can someone help me?
Upvotes: 3
Views: 12354
Reputation: 14467
Just adding to Charliehorse55's answer.
Usually one does an argument reduction using simple trigonometry
cos(x + y) = cos(x)cos(y) - sin(x)sin(y)
sin(x + y) = cos(x)sin(y) + sin(x)cos(y)
to reduce the argument to [0..SmallAngle] range and only then calculate the Taylor expansion.
Upvotes: 4
Reputation: 2000
The bug lies in the condition of your while loop:
while (term >= epsilon && -term <= epsilon)
It's not the correct condition. While it could be fixed by fixing the logic:
while (term >= epsilon || -term >= epsilon)
You should just use the standard floating point abs function, fabs
, as it makes the function of your code more obvious:
while (fabs(term) >= epsilon)
After applying that change and compiling your program I used it to compute cos(3.141593) = -1.000004
, which is correct.
Upvotes: 5