I'm working on a project for our school and we are required to create a program that computes the approximation of the Taylor Expansion Series of sin x
and cos x
, only using <stdio.h>
and without user-defined functions other than int main()
, of all angles from -180
to 180
in increments of +5
. the following is my code:
#include <stdio.h>
#define PI 3.141592653589
#define NUMBER_OF_TERMS 10
int
main()
{
int cosctr, sinctr;
double ctr, radi;
double cosaccu, costerm, sinaccu, sinterm;
for (ctr = -180; ctr < 185; ctr = ctr + 5) {
radi = ctr * PI/180.0;
cosctr = 1;
cosaccu = 1;
costerm = 1;
sinctr = 2;
sinaccu = radi;
sinterm = radi;
while (cosctr <= 2*NUMBER_OF_TERMS) {
costerm = costerm*(-1)*(radi*radi)/(cosctr*(cosctr + 1));
cosaccu = cosaccu + costerm;
cosctr+=2;
} do {
sinterm = sinterm*(-1)*(radi*radi)/(sinctr*(sinctr + 1));
sinaccu = sinaccu + sinterm;
sinctr+=2;
} while (sinctr <= 2*NUMBER_OF_TERMS);
printf("%.2lf %.12lf %.12lf %.12lf\n", ctr, radi, cosaccu, sinaccu);
} return 0;
}
The code above is accurate for a 15 terms expansion approximation. however, if I change NUMBER_OF_TERMS
to, for example, 5 or 10, the approximation is flawed.
Any suggestions?
Let me clarify: I need to obtain an approximation of 5 terms, 10 terms, and 15 terms. I cannot use any other library other than <stdio.h>
. I cannot use any other functions outside of int main()
(I apologize for the vagueness of my explanation before).
Please answer with the included corrected code.
The Taylor expansions of sin(x) and cos(x) takes longer to converge as x increases. But since these are periodic functions, you don't actually need to bother expanding the series for values outside the range 0-90°.
For values of x outside this range, use the following identities:
For example, sin(175°) = sin(5°), cos(-120°) = -cos(60°)
I tried your code; it works fine for me, in that it does what it looks like it's designed to do. Here's a comparison between your code's output for the cosine at 5 and 10 terms and the same approximation as calculated by Mathematica. They agree up to
<10^-12
, i.e. your outputted precision.:The only problem I see with your code is that, with the way you designed your loops, you're actually taking into account
NUMBER_OF_TERMS + 1
terms if you count the first terms in the expansion (i.e. the constant term for the cosine, the linear term for the sine.) You start with this first term, and then your loop adds anotherNUMMBER_OF_TERMS
terms. If that is not by design, you're actually approximating the functions with higher precision that you are expecting.By its very definition, a Taylor series is a summation of an infinite series of terms.
Thus, a Taylor finite expansion only is an approximation of the true result: as the number of terms increases, the accuracy of this approximation improves.
If there are enough terms, the approximation error at some point becomes unnoticeable. However, if you try lowering the number of terms, the approximation error increases and can detected.
In your case, the approximation error is below the detection threshold for
NUMBER_OF_TERMS
= 15, but becomes noticeable whenNUMBER_OF_TERMS
= 10 or less.i figured it out with help from another user. turns out i was calculating terms + 1, making the answer more accurate than intended. after 15 terms the changes are past the 12th decimal point, and therefore did not show on the results.
The key to high precession, yet simple calculation of
sind(degrees)
andcosd(degrees)
is to reduce the range of degree to 0 to 90 first (or even 0 to 45), using the usual trigonometric adjustments with degree arrangements first.Reductions:
angle = fmod(angle, 360)
// reduce (-360..360) or use a = a - (int)(a/360)sin(x) = -sin(-x)
// reduce to [0..360)cos(x) = cos(-x)
// reduce to [0..360)sin(x) = -sin(x-180)
// reduce to [0..180)cos(x) = -cos(x-180)
// reduce to [0..180)sin(x) = cos(90-x)
// reduce to [0..90)Further reductions:
For [45-90) use
sin(x) = cos(90-x)
// reduce to [0..45)then convert to radians and use Taylor series expansion.
Example
Note: Since code is dealing with
double
, typically 17 digits of precision, no need to use a course PI approximation.