I am only allowed to use int, unsigned int and float. Must be accurate to the 7th significant digit. Currently I overflow 'float top' at an x value greater than 13. Thank you for your time.

#include <iostream>
#include <iomanip>
using namespace std;

float sum=1,x, top=1,factoral=1;

int main(void)
{
cout << "f(x) = e^x, if x = ";
   cin >> x;
   
   for(int i=1; i<=34; i++)
   {
      factoral*=i;
      top *= x;
      sum += top/factoral;
      
   }
   cout << "Then f(" << x << ") = " << setprecision(7) << sum <<endl;;
   return EXIT_SUCESS;
   
}

Recommended Answers

All 13 Replies

This is a very naive way to calculate power series. I bet you overflow the integer factorial much earlier.
If you look closely, the series can be rewritten as
1 + x*(1 + (x/2)*(1 + (x/3)*(..... *(1 + (x/n))))...)))
Now calculate it "from inside".

I am only allowed to use int, unsigned int and float. Must be accurate to the 7th significant digit. Currently I overflow 'float top' at an x value greater than 13. Thank you for your time.

Meaning?
What were you expecting as an answer?

"I am only allowed to use int, unsigned int and float .Must be accurate to the 7th significant digit"

Meaning that I didn't post on a forum at the first spot of trouble, that I've been at this for hours. I've found plenty of solutions to this problem but they have all used longs or doubles and the assignment given by my professor has those requirements.

"Currently I overflow 'float top' at an x value greater than 13."

Meaning that I spend time looking through my own code to find what was causing my errors.

"Thank you for your time."

Meaning that I was thanking people from taking time out of their lives to look at a problem that I am having.

And I'm not looking for an answer I don't want someone to write my code for me, I'm looking for assistance. If this is not the proper forum for such requests I'm sorry.

And I'm not looking for an answer I don't want someone to write my code for me, I'm looking for assistance. If this is not the proper forum for such requests I'm sorry.

Please exhale. Relax. Read my post (it is just above), if you haven't done it yet. Understand why this calculation schedule avoids overflows and a whole lot of other numerical problems. Realize that it is a standard way of calculating power series. Implement it. And enjoy.

You seem to have misinterpreted my question. I was not assuming you just blew in here for us to write your code for you -- although that does happen far too often. I meant:

"Currently I overflow 'float top' at an x value greater than 13."

I wanted a better explanation of what this meant so I know for sure.

What were you expecting as an answer?

What did you get for output and what did you want for output? I can't see your screen so you must give us the details.

My guess is you are overflowing the precision capabilities of the float type.

Using WaltP's advice I rewrote my code. (Thank You)

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

float sum=1,subtotal=1,x;

int main(void)
{
cout << "f(x) = e^x, if x = ";
   cin >> x;
   
   for (int i = 1; i < 100; i++)
   {
      subtotal *= x/i;
      sum += subtotal;
   }
   cout << "Then f(" << x << ") = " << setprecision(7) << sum <<endl;;
   if(sum == exp(x))
      cout << "And the math library agress" << endl;
      else
      cout << "The Math library disagrees by: " << sum - exp(x) << endl;
   
   return EXIT_SUCCESS;
}

Here are a few results:

tk-mbp:~ Tim$ /Users/Tim/Documents/ENGR101/hw3c/build/Debug/hw3c
f(x) = e^x, if x = -2
Then f(-2) = 0.1353353
The Math library disagrees by: -1.664649e-08
tk-mbp:~ Tim$ /Users/Tim/Documents/ENGR101/hw3c/build/Debug/hw3c
f(x) = e^x, if x = 1
Then f(1) = 2.718282
The Math library disagrees by: 1.558702e-07
tk-mbp:~ Tim$ /Users/Tim/Documents/ENGR101/hw3c/build/Debug/hw3c
f(x) = e^x, if x = 10
Then f(10) = 22026.46
The Math library disagrees by: -0.0009510567
tk-mbp:~ Tim$ /Users/Tim/Documents/ENGR101/hw3c/build/Debug/hw3c
f(x) = e^x, if x = 100
Then f(100) = inf
The Math library disagrees by: inf

Sounds like it worked... welcome.

I've been trying to find ways to improve precision because according to my professor "Note that it is possible to calculate the exponential as well as the math library exponential function." I modified my program to batch output results. And as x->inf the variance starts becoming massive.

Batch Output [-1,100]

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

float sum=1,subtotal=1,x;

int main(void)
{
//cout << "f(x) = e^x, if x = ";
  // cin >> x;
   
   for(x=-1;x<100;x++){
      sum=1,subtotal=1;
   
      for (int i = 1; i < 100; i++)
      {
         subtotal *= x/i;
         sum += subtotal;
      }
      
   cout << "Then f(" << x << ") = " << setprecision(7) << sum <<endl;;
   if(sum == exp(x))
      cout << "And the math library agress" << endl;
      else
      cout << "The Math library disagrees by: " << sum - exp(x) << endl;
   }
   return EXIT_SUCCESS;
   
}

See this for a reference. The way you are expressing e^x is for the Taylor series centered around 0. There is a corrective factor of -a (so you substitute x-a for x in your equation) to get a better approximation for the series centered around a. I'm not sure how often you'd have to recalculate it to keep the accuracy up.
You're assuming that the cmath function uses a plain Taylor series about zero but there are probably better approximations out there.

EDIT: Further probing got me that the library probably uses minimax polynomials rather than the Taylor series. See http://mathworld.wolfram.com/EllipticRationalFunction.html and its related articles if you're interested. Otherwise I can't think of any way to make your Taylor series more accurate other than to recalculate it with a new center spaced at +10 from the prior center (that's just my own speculation I don't know if the theory supports it).

Maybe I misunderstood but e^(x-a) just shifts the entire estimate over, it does not make it more precise. If that is how you meant to modify the code.

for (int i = 1; i < 100; i++)
      {
         subtotal *= (x-3)/i;
         sum += subtotal;
      }

You modified the code correctly. I probably should have worded what I said a bit differently. The "offset" is actually part of the Taylor series yielding an approximation around that certain point a. The series you had programmed is around a = 0, which collapsed all of the x-a terms into x (see the first line under the http://en.wikipedia.org/wiki/Taylor_series#Definition heading), so I was merely saying put the x-a terms back in where they belonged. Having done that you could re-evaluate for increasing a.

OK, now you are getting somewhere. There still are few problems with this code.

First of all, I ran your code and I observed that the last reasonable result is obtained at x being equal to 88, where the calculated value becomes 1.4672884e+38 (the math library reports 1.6516363e+38). This is suspiciously close to 3.40282347e+38, which is MAXFLOAT as defined in <math.h>. Since then, your code reports inf, and the math library reports nan. Close enough.

However, things really start to deteriorate from x reaching 55. Until then, the relative error stays in e-7 range. From 55 up it starts growing up quickly. Which brigs the question on the loop termination condition. You break the loop after a 100 iterations. A hundred is a good number. It is big and round, but I'd like to see some logics behind it.

Using WaltP's advice I rewrote my code. (Thank You)

I don't know about WaltP's advice, it is definitely not an advice I gave you. The Horner schema advised by me kept stable - with the same 100 iterations - all the way to 60. Please meditate over this.

How about estimating e^-x ...
of course not doing 1/e^x

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.