Taylor Series Expansion: cos(x) range issue

I have been able to compile with g++ and run this code for a range of degree values -95<x<95, but any degree value outside of this range enters an infinite nan loop. I found this while testing, but I cannot discern where the issue lies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <cmath>

using namespace std;

const double pi = 3.141592653589;

//factorial function
int factorial(int n)
{
  if ((n == 0) || (n==1)) return 1;
  return (n*factorial(n-1));
}


// Main function
int main()
{
  // statements
  double x,sign,cosx,contribution,rads;
  double epsilon; 
  
  // request and print x
  cout << "Please input value of x in degrees for evaluating function cos(x)" << endl;
  cin >> x;
  cout << "x = " << x << endl;
  
  // convert degrees to radians
  rads=x*pi/180.0;

  // evaluate the Taylor Series Expansion for cos(x)
  cosx = 0;
  sign = -1;
  epsilon =0.000001;
  contribution = epsilon+1;

  for (int i=0; abs(contribution)>=epsilon; i++)
  {
    contribution = pow(sign,i)*pow(rads,2*i)/factorial(2*i);
    cosx=cosx+contribution;
    cout << "Term contribution is: " << contribution << endl;
    cout << "The function with " << i << " terms is: " << cosx << endl;
  }


  // Print the value of the functino with each addiitonal term

  return 0;
}
You are calculating each term from scratch and factorials grow far too fast to work them out like this. Also, it is overkill to use a power function just to select sign +1 or -1.

For most power series, it is easier, more efficient and less prone to overflow to calculate each term as a multiple of the previous one. For the cosine series,
first term = 1
next term = - previous term * rads * rads / (1 * 2)
next term = - previous term * rads * rads / (3 * 4)
next term = - previous term * rads * rads / (5 * 6)
etc.
Each of those 'terms' could happily be stored in your variable 'contribution'.
You should be able to see that this is mathematically equivalent to yours, but is less prone to overflow.

Mathematically, you could also expand about other points than 0 if you wanted.
I tried implementing the following lines, but now I receive an error telling me that the next_term is complex.

Edit:
error: cannot convert ‘__complex__ double’ to ‘double’ in assignment
next_term = -next_term*rads*rads/((i+1)*2i);

1
2
3
4
5

    first_term  = 1;
    next_term = -next_term*rads*rads/((i+1)*2i);
    contribution = first_term + next_term;
Last edited on
You aren't using complex numbers - no idea where that message is coming from unless you have changed more than you are showing. Or maybe it misinterprets your (incorrect) 2i as a complex number.

You should be dividing by ((2*i-1) * 2 * i ), not what you have written.

Why not have a single variable called contribution: this is what you initialise to 1 and then multiply by a new factor each time. You don't need 3 lines like this.

Make sure you understand what you are doing mathematically- your coding above is slightly 'random'.


Ah yes, this makes the error more obvious. I will give it another shot. Thank you
Topic archived. No new replies allowed.