calculating e^x without using exp() function

Hello, all. I am a freshman in college, and fairly new to coding. In my Computer Science I class, I have been assigned to code a function that calculates e^x without using the exp() function. The assignment before asked me to create a function that calculated the factorial of a number, and this assignment is asking me to implement my factorial function into my e^x function. My question is how could I implement my factorial function into my e^x function and have it work properly? I suspect that it's my limited knowledge of function calls and how they work. Here is my code so far. My professor was gracious enough to supply some starter code, and I've since built on it.

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
// Program: exp.cpp
// Description: Test and develop a version of the exp() function - main() has test
// code to check and see if this version of exp() function works properly.

#include <iostream>
#include <cmath>
#include <cstdlib>

using namespace std;

// double factorial(int N) - returns the factorial variable N
// Please add the code necessary to calculate the factorial of the number represented by N

double factorial(double N) {
    double return_val = 1;

    for(int i = 1; i <= N; i++){
        return_val = return_val * i;
    }

    return return_val;
}

// A clone of the system exp() function.
// Please do not use the system exp() function in the creation of your function.
double E_to_X(double X) {
    double i, e = 0, total = 0;

    for(i = 0; i <= X; i++){
        e = pow(X, i) / factorial(X);
        total = total + e;
    }

    return total;
}

// You can change main() in anyway you want
int main() {

    cout << fixed << "E_to_X(0) is " << E_to_X(0) << " should be 1" << endl;
    cout << fixed << "E_to_X(1) is " << E_to_X(1) << " should be 2.718" << endl;
    cout << fixed << "E_to_X(2) is " << E_to_X(2) << " should be 7.38" << endl;
    cout << fixed << "E_to_X(3) is " << E_to_X(3) << " should be 20.006" << endl;
    cout << fixed << "E_to_X(4) is " << E_to_X(4) << " should be 58.64" << endl;
    cout << fixed << "E_to_X(5) is " << E_to_X(5) << " should be 120" << endl;
    cout << fixed << "E_to_X(10) is " << E_to_X(10) << " should be 22026" << endl;

    return 0;
}
Last edited on
Why do you think you should only loop up to X in line 29? After all, exp(x) is an infinite series and, whilst I wouldn't expect you to loop indefinitely, there's no reason you should stop at about X terms. Base a loop termination criterion on how small your term has got. Presumably you also meant factorial(i) rather than factorial(X) on line 30, and that this function would take an int, not double, argument on line 14. Your loop variable, i, should also be an int (lines 27-30).

By the way, using pow() and factorial() functions is a dreadful way to evaluate this series (even if they are written like that in the definition). I sincerely hope your instructor didn't actually ask you to use them. A far better way, for this and many other series functions, is to note that each new term is a simple multiple of the previous. Here,
(ith term) = (previous term) * X / i
That's much easier than having to deal with exploding powers of X, or even more explosively growing factorials.
Last edited on
this assignment is asking me to implement my factorial function into my e^x function
This suggests they want you to implement an approximation of exp() through a Taylor series.

https://en.wikipedia.org/wiki/Taylor_series
I only loop to X in the for loop in the function E_to_X because in the cout statements in the main function, they are passing a top bound to the X. The formula they gave for us to follow is:

e^x = 1 + x^1/1! + x^2/2! + x^3/3! + ……….

which I believe is a Taylor series as helios described. Basically, they want me to loop until a certain value X is reached and then display the sum of all the iterations of the loop.
In the cout statements in the main function they are passing THE VALUE OF X. Look at your function declaration. I can assure you this has nothing to do with the number of terms.

But you are quite entitled to do it your own way.
Oh, I see what you mean now about passing the value of X. I gave my code a second look and the way you described it makes more sense. Unfortunately, they do want me to call my factorial function when calculating the value of e^X. How could that be implemented into the solution you provided?
You need to fix all the items in the first paragraph of my first reply. The second paragraph - getting rid of the factorial and power functions - is for another day.
Sorry for all the questions, but what is meant when you say "Base a loop termination criterion on how small your term has got"? Here's my output with all of the changes except for the whole "Looping to X" thing because i don't know what else I would loop to:

E_to_X(0) is 1.000000 should be 1
E_to_X(1) is 2.000000 should be 2.718
E_to_X(2) is 5.000000 should be 7.38
E_to_X(5) is 91.416667 should be 120
E_to_X(10) is 12842.305115 should be 22026
Press <RETURN> to close this window...
You have a loop in lines 29 to 32 which sums the first few terms in a Taylor series for exp(x). At the moment you stop looping after i reaches X, which actually means you stop (and hence truncate the Taylor series) at the largest term in the series. You need a stop-looping criterion which cuts in when the absolute size of a term gets sufficiently small, say 1e-10.

If you have everything else correct then start with a fixed number of loops - say 20. This should give a decent answer for small values of x. Then think how you could terminate the loop based on a small value of abs(e).
1
2
3
4
5
6
7
8
9
consider 
double pwr = 1.0;

 for(i = 0; i <= 5; i++){  //5 terms enough? 
        e = pwr / factorial(X);
        total += e;
        pwr *= X; //power...
    }


not because we care how fast this is but because thinking this way now lets you see it later when speed may matter more than it does for an assignment.
Last edited on
This may come off as a dumb question, but what are you referring to when you say "the absolute size of a term"? Are you talking about the byte-size of a term or is there something else meant by "absolute size" that I haven't learned?
The "absolute size" meaning the magnitude regardless of whether it is positive or negative.

e.g. abs(5) = abs(-5) =5.

Although none of your tests use a negative x, exp(x) is perfectly well defined for negative x.

This becomes relevant only when you test for small with < ("less than"). -20 is < 1e-10 ... but nobody would regard it as small in magnitude.
I've been tossing this around in my mind for over an hour but I just can't seem to figure it out. The only value that comes to mind is zero. Something like:

1
2
3
4
for(int i = 0; i <= 0; i++){
        e = pow(X, i) / factorial(i);
        total = total + e;
    }


But that returns all of my cout statements as 1.0. The only other thing I could think of was setting i <= (e <= 0), but that returns all my cout statements to 1.0 as well. I can't wrap my head around it.
Your criterion to continue looping is currently i<=0, or effectively i==0, which means you only get the first term, 1.0. You have a major misunderstanding if you think the loop criterion (middle part of the for statement) always has to contain i.

Your criterion should be based on the size of term, e. Say, abs(e) > 1.0e-10 (note the "greater than" sign - you want this loop to run whilst terms are big). To ensure that this loops the first time you should make sure that e is initialised to something larger (say, 1) rather than the e=0 which you have at present.

Thus:
1
2
3
    double e = 1, total = 0;

    for(int i = 0; abs(e) > 1.0e-10; i++){


IMPORTANT: before you say "but I still get the wrong answers", you also need to check the answers you are "supposed" to get. For example,
exp(2) is 7.389 (or 7.39 to 2 d.p.)
exp(3) is 20.0855
exp(4) is 54.598
exp(5) is 148.413 - your version is seriously wrong here.
You can easily verify these on a calculator.

It would also be worth checking some NEGATIVE values of x. (This is where the abs(e) rather than just e comes in.)

If you still have problems then please post the whole code.
Last edited on
I guess I'm still not fully understanding why the terms need to be big. I got the right answers when I implemented your code, but I want to know why that worked rather than just accept it as the right answer. I know I'm still new, but I really do want to grow as a coder and I think this is something I want to be able to do for the rest of my life.
Last edited on
You are summing an infinite power series. You have to keep summing while the terms are "big" and stop summing once they are "small". The condition in the middle of the for loop is that to "keep summing".

I hope that this helps. Good luck in advancing your coding skills.
OK that makes a lot of sense now that you've explained it that way. Thank you so much for your help!
Last edited on
Topic archived. No new replies allowed.