Ok, you've made a quite credible effort on this. (Sad how too many students cannot bother in the least. So my congratulations are due.)
It looks like your computation of the value of n that yields a term under the threshold seems right. Nicely done there in a loop, going from term to term by multiplying by pi/n, since you are given that x does not exceed pi. The value of n here is appropriate for the exponential series, and since the cosine series essentially uses the even order terms from the exponential one, this could work, IF you were careful in the last step.
It is in the last step that you had a problem. Actually, several of them.
x = -pi:0.01:pi;
cos_approx = x;
for i = 1:n
cos_approx = cos_approx + (((-1)^i) / factorial(2*i)) *(x.^(2*i));
end
trunc_error = abs(cos_approx - sin(x))
You use the colon operator to compute x. See that this does NOT end up at pi for the last term, but a little short.
x = -pi:0.01:pi;
x(end)
ans =
3.13840734641021
Better is to use linspace. Since there were 629 steps in the colon call, I'll use the same number of elements.
x = linspace(-pi,pi,629);
x(end)
ans =
3.14159265358979
The zero'th order term in the cosine series is 1. Instead, you set cos_approx to x. (That would be correct for the linear term in the sine series.)
Then at the end, you subtract sin(x) from the cosine approximation. So I think you have some code for a sine approximation and the cosine approximation confused.
I also see that you did not use a loop that computes each term in the series as you did before.
Finally, you had one more problem. You used the value of n that would work for an exponential series. But the cosine series uses only every OTHER term in that series.
The simple solution is to aggregate the pair of loops into ONE loop. I'll set it such that it computes each term from the previous one, AND does the test to determine when to stop in this same loop.
x = linspace(-pi,pi,629);
cos_term = ones(size(x));
cos_approx = cos_term;
xsquared = x.^2;
n = 2;
while abs(cos_term(end)) > Threshold
cos_term = - cos_term.*xsquared./(n*(n-1));
cos_approx = cos_approx + cos_term;
n = n + 2;
end
trunc_error = abs(cos_approx - cos(x));
So the above loop is similar to your two loops.
The cos_term that I compared to the threshold at each step was JUST larger then that threshold for the next to last step.
ans =
1.37686472803774e-12
ans =
-2.09063233531477e-14
Better code might had allowed the loop to terminate sooner for each value of x independently, based on the specific term for that value.
Best Answer
(Note: you might decide to read how I coded trig functions in my HPF toolbox. But that would be wild overkill for basic homework.)
So, think. What does this do for you?
Where does Xhat live, as compared to x? What do you know about sin(Xhat), as compared to sin(x)? If you are not sure, try some values! Play around. THINK! For example...
Can you do better? Of course. The Taylor series for the sine function will converge better if Xhat lives in the range [-pi,pi), instead of [0,2*pi).
You can pretty easily deal with that, since you would have this identity:
That suggests you can do this:
Where does Xhat now live?
Can you do better? Well, yes. You can reduce the range further. You will first need to decide if you can get satisfactory convergence over that interval, with a reasonable number of terms. For example, if you look at the series for sin(x). Those terms are largest when x is large.
You just need to take a few more terms for the larger domain.
In fact, there are some simple tricks to further reduce the domain of interest. For example, if you do range reduction to +/-pi/4, the series will converge much faster yet. But you may choose a larger interval, just accepting a few more terms in the series. The tradeoff will then be between number of terms and complexity in the range reduction.