Taylor series approximation

Hi there,

I have written the following code for a program which calculates and outputs the taylor series approximation for e^x. The formula is:
e^x = Σ [x^n] / n!= 1 +x + x²/2 +...

It receives an input value for x from a file and outputs the result to a file. The program works fine, but I have a few questions:

1) Why, if I change "float fact" to and integer does the program output infinity as the result?

2) If I change the counter to 1000 instead of 100, I get an output of NaN. What does this mean? If it means that the data type is not big enough, what can I do to correct this and obtain a more accurate result? Why isn't double big enough?

3) Is there a way of setting precision locally, instead of having to place braces to limit setprecision's scope?

4) How would I receive multiple values stored in the file "input.txt", evaluate all of them and then output the result?

5) Is there anything that should be changed in the code below to make it more efficient/correct?

Many thanks :)


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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <cmath>
#include <fstream>
#include <iomanip>
using namespace std;

// Function prototypes (see explanation below):
void getValues( float &x );
float expApprox( float xInput );
float factorial( int counter );
void displayResult( double expAnswer, float x );

int main()
{
    //Declare local variables:
    double expAnswer = 0;        // stores appoximation answer
    float x = 0;                // stores input value for x

    // get a value stored in input.txt
    getValues( x );

    // calculate exponent approx using input value from file
    expAnswer = expApprox( x );

    displayResult( expAnswer, x );

    return 0;
}

void getValues( float &x )
{
    float xTemp = 0;

    ifstream inFile;
    inFile.open ("input.txt");
        inFile >> xTemp;

    //validation for the input number:
    while ( xTemp > 50 )
    {
        cout << "Invalid number! New number taken." << endl;
        inFile >> xTemp;
    }

    x = xTemp;
}

float expApprox( float xInput )
{
    double expAnswer = 1;    // initialise to 1 in order to include the first term with 0!

    //for loop to calculate value for exponent approximation
    for ( int counter = 1; counter <= 100; counter++ )
    {
        expAnswer = expAnswer + ( pow( xInput, counter ) / factorial( counter ) );
    }

    //return the answer to main function
    return expAnswer;
}

float factorial( int counter )
{
    float fact = 1;

    // calculates the factorial for each iteration
    for ( int i = 1; i <= counter; i++ )
    {
        fact = fact * i;
    }

    return fact;
}

void displayResult( double expAnswer, float x )
{
    {
        cout << "The answer for the approximation to e^" << x << " is " << setprecision( 5 ) << fixed << expAnswer << endl;
    }

    ofstream myFile;
    myFile.open ("output.txt");

    {
        myFile << "The answer for the approximation to e^" << x << " is " << setprecision( 5 ) << fixed << expAnswer << endl;
    }
    return;
}
1, 2)
A floating point number can hold larger numbers than can the largest integer.

However, FP numbers are not continuous. They are, at best, an approximation to the the desired value. If you want arbitrary-precision numbers, I recommend you to the GNU MP Bignum library
http://gmplib.org/

3)
The setprecision() manipulator can be thought of as a function taking an argument affecting the state of an I/O stream. I'm not sure that using the braces is actually making any difference, or whether it should be expected to do that anyway. (But I'm not a language lawyer.)

You can read and restore the state of a stream (like cout), but it is simply best to set your precision, fixed, etc before every set of operations operation that requires it to be that way. For an output operator, use
http://www.cplusplus.com/reference/iostream/ios_base/precision.html
to preserve the precision if you need to change it.

In your example, there is no reason to try to use it only locally.

4)
Typically, you would open the file in main() instead of getValues(), then put it all in a loop:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  inFile.open( ... );

  // Get the first value (if any)
  getValue( inFile, x );

  while (inFile)  // While there are values (or at least no errors)
    {
    // Calculate and display the Taylor series
    expAnswer = expApprox( x );
    displayResult( expAnswer, x );

    // Get the next value (if any)
    getValue( inFile, x );
    }

  inFile.close();
Notice how the file is passed as a variable reference to getValue() as well as the result.

5)
To late to think that hard. Looks good enough to me.

Hmm, I'd probably return the value as x = getValue( inFile );

Hope this helps.
Hi Duaos,

Thanks for this thorough and helpful reply!

The reason I wanted to limit setprecision locally was so that I didn't get an output of, say,

The answer for the approximation to e^2.000000 is 7.389056


Rather I wanted just 2. If I setprecion after the 2, this would then affect the theoretical value output, which I also didn't want.

Thanks again!
Your input and output precisions should generally match (or at least, the output precision should not be greater than the input precision[s]).

The x variable is declared as a float. I presumed that your input file could supply a rational exponent. Is this not the case?

Glad to be of help. :-)
Wow that was a quick reply :D

Yep x is a float, and the input can be rational. I just thought that if the input is an integer, it looks pretty strange to have all those 0's!

I suppose it doesn't really matter... it was just to test the concept of setprecision.
Topic archived. No new replies allowed.