Trying to compute e^x when x_0 = 1

214 views Asked by At

I am trying to compute the Taylor series expansion for e^x at x_0 = 1. I am having a very hard time understanding what it really is I am looking for. I am pretty sure I am trying to find a decimal approximation for when e^x when x_0 = 1 is. However, when I run this code when x_0 is = 0, I get the wrong output. Which leads me to believe that I am computing this incorrectly.

Here is my class e.hpp

#ifndef E_HPP
#define E_HPP

class E
{
    public:
        int factorial(int n);
        double computeE();

    private:
        int fact = 1;
        int x_0 = 1;
        int x = 1;
        int N = 10;
        double e = 2.718;
        double sum = 0.0;

};

Here is my e.cpp

#include "e.hpp"
#include <cmath>
#include <iostream>

int E::factorial(int n)
{
    if(n == 0) return 1;
    for(int i = 1; i <= n; ++i)
    {
        fact = fact * i;
    }

    return fact;
}

double E::computeE()
{
    sum = std::pow(e,x_0);

    for(int i = 1; i < N; ++i)
    {
        sum += ((std::pow(x-x_0,i))/factorial(i));
    }
    return e * sum;
}

In main.cpp

#include "e.hpp"
#include <iostream>
#include <cmath>

int main()
{
    E a;
    std::cout << "E calculated at x_0 = 1: " << a.computeE() << std::endl;
    std::cout << "E Calculated with std::exp: " << std::exp(1) << std::endl;
}

Output:
E calculated at x_0 = 1: 7.38752
E calculated with std::exp: 2.71828

When I change to x_0 = 0.
E calculated at x_0 = 0: 7.03102
E calculated with std::exp: 2.71828

What am I doing wrong? Am I implementing the Taylor Series incorrectly? Is my logic incorrect somewhere?

3

There are 3 answers

4
jcarpenter2 On BEST ANSWER

Yeah, your logic is incorrect somewhere.

Like Dan says, you have to reset fact to 1 each time you calculate the factorial. You might even make it local to the factorial function.

In the return statement of computeE you are multiplying the sum by e, which you do not need to do. The sum is already the taylor approximation of e^x.

The taylor series for e^x about 0 is sum _i=0 ^i=infinity (x^i / i!), so x_0 should indeed be 0 in your program.

Technically your computeE computes the right value for sum when you have x_0=0, but it's kind of strange. The taylor series starts at i=0, but you start the loop with i=1. However, the first term of the taylor series is x^0 / 0! = 1 and you initialize sum to std::pow(e, x_0) = std::pow(e, 0) = 1 so it works out mathematically.

(Your computeE function also computed the right value for sum when you had x_0 = 1. You initialized sum to std::pow(e, 1) = e, and then the for loop didn't change its value at all because x - x_0 = 0.)

However, as I said, in either case you don't need to multiply it by e in the return statement.

I would change the computeE code to this:

double E::computeE()
{
    sum = 0;
    for(int i = 0; i < N; ++i)
    {
        sum += ((std::pow(x-x_0,i))/factorial(i));
        cout << sum << endl;
    }
    return sum;
}

and set x_0 = 0.

3
Dan Byström On

"fact" must be reset to 1 each time you calculate factorial. It should be a local variable instead of a class variable.

When "fact" is a class varable, and you let "factorial" change it to, say 6, that means that it will have the vaule 6 when you call "factorial" a second time. And this will only get worse. Remove your declaration of "fact" and use this instead:

int E::factorial(int n)
{
    int fact = 1;
    if(n == 0) return 1;
    for(int i = 1; i <= n; ++i)
    {
        fact = fact * i;
    }

    return fact;
}
0
duffymo On

Write less code.

Don't use factorial.

Here it is in Java. You should have no trouble converting this to C++:

/**
 * @link https://stackoverflow.com/questions/46148579/trying-to-compute-ex-when-x-0-1
 * @link https://en.wikipedia.org/wiki/Taylor_series
 */
public class TaylorSeries {

    private static final int DEFAULT_NUM_TERMS = 50;

    public static void main(String[] args) {
        int xmax = (args.length > 0) ? Integer.valueOf(args[0]) : 10;
        for (int i = 0; i < xmax; ++i) {
            System.out.println(String.format("x: %10.5f series exp(x): %10.5f function exp(x): %10.5f", (double)i, exp(i), Math.exp(i)));
        }
    }

    public static double exp(double x) {
        return exp(DEFAULT_NUM_TERMS, x);
    }

    // This is the Taylor series for exp that you want to port to C++
    public static double exp(int n, double x) {
        double value = 1.0;
        double term = 1.0;
        for (int i = 1; i <= n; ++i) {
            term *= x/i;
            value += term;
        }
        return value;
    }
}