2

I am fairly new to c++ and writing a program to calculate the approximate value of e^x. Given by the formula:

1 + X + X^2/2! + ... + X^n/n!  (for values of n from 1-100)

The program calculates the value perfectly until the user enters a number for "xValue" larger than 60 (ie. 61 or greater). I am unsure why this is and would really appreciate some feedback:

void calculate_sum(CalculateEx& numberSum)
{   
    double factoralSum;


    numberSum.xTotal = numberSum.xValue;
    numberSum.xTotal++;

    for (double counter = 2; counter <= 100; counter++)
        {
            factoralSum = 1;

            for (double factoral = 1; factoral <= counter; factoral++)
                {
                    factoralSum *= factoral;
                }

            numberSum.xNextValue = pow(numberSum.xValue, counter) / factoralSum;
            numberSum.xTotal += numberSum.xNextValue;
        }

    return;
}
Barmar
  • 596,455
  • 48
  • 393
  • 495
  • 3
    Do you realize how big 100! is? Way too big to fit in a `double`. – chris Aug 12 '14 at 19:32
  • 1
    BTW, it's very approximately 10^158. – Mad Physicist Aug 12 '14 at 19:42
  • Can you show some inputs and outputs (e.g., for `xValue=61`), and explain a bit more what's going wrong with `xValue = 61`? Are you getting inaccurate results? A crash? Some other problem? @chris: 100! fits easily in a double. 171! is the smallest factorial that overflows the range of a double. – Mark Dickinson Aug 12 '14 at 19:59
  • @MarkDickinson, Well crap, I fail. I forgot those things normally go to about 10³⁰⁰ and how absurdly large that number is. – chris Aug 12 '14 at 20:01
  • is there such a thing as a long long double that could fit 100!? – drunkenmonkey44 Aug 12 '14 at 20:04
  • @drunkenmonkey44 100!, as said above, is about 10^158. `double` (or `long double`) holds up to about 10^308, it is quite enough. – mikhail Aug 12 '14 at 20:12

3 Answers3

2

Don't calculate the next row element from scratch, store the previous one, x^(n+1)/(n+1)! == (x^n)/n! * x/(n+1). This way you won't have to store values of x^n and especially n! separately (they are simply too big to fit in any reasonable type), whereas the values of x^n/n! converge to 0 as n rises.

Doing something like this would do:

double prevValue = 1;
sum = prevValue;
for (size_t power = 1; power < limit; ++power) {
    prevValue *= x / (n + 1);
    sum += prevValue;
}
mikhail
  • 465
  • 5
  • 16
  • That is a much better solution, but the actual sum of the formula can reach values that require e+300. Is there a type large enough to accommodate this? – drunkenmonkey44 Aug 12 '14 at 19:47
  • @drunkenmonkey44 `std::numeric_limits::min()` or `::max()` (from `#include `) tells me, that `long double` can hold values from 2.22507e-308 to 1.79769e+308 (in absolute values). Although I am not sure about the precision near its higher limit, but with e+300 you would *probably* be ok. – mikhail Aug 12 '14 at 19:57
  • @drunkenmonkey44 In MS's C++ `long double` seems to be equivalent to simply `double`, btw. Maybe g++ has a different opinion, can't check right now. – mikhail Aug 12 '14 at 20:11
0

Even a double can only fit so many digits. The computer always has a limit. I know nothing about scientific computing, but I suppose if you wanted greater precision you might have to find a quad-precision floating point number or something.

Cinch
  • 839
  • 8
  • 25
0

Your program is attempting to calculate numbers that are out of the range of normal doubles. You can verify this by printing the value of factoralSum after the loop in which it is computed. If you insist on using the Taylor expansion, you may want to check the value of DBL_MAX in <float.h>

Java has a class called BigDecimal, which lets you create numbers with arbitrarily large precision. In C++, you may want to reference this question: Is there a C++ equivalent to Java's BigDecimal?

Community
  • 1
  • 1
Mad Physicist
  • 76,709
  • 19
  • 122
  • 186
  • Ah I see. Is there a type that has the potential to store up to E100+? – drunkenmonkey44 Aug 12 '14 at 19:42
  • This doesn't add up, though. For a value of `61` (which the OP says is causing problems), `pow(61, 100)` and `factorial(100)` are both well within the range of a double, as is the final result of `exp(61)`. – Mark Dickinson Aug 12 '14 at 19:45
  • They are well within range, but anything you try to add to them will be lost. Or of you try to add the reciprocal of them to something, they will be lost. – Mad Physicist Aug 12 '14 at 19:49
  • The problem comes when printing "xTotal" as the formula results in values as large as 2.756 E+304. Id there a type that can accommodate a value this large? – drunkenmonkey44 Aug 12 '14 at 19:51
  • @drunkenmonkey44: What inputs are you giving which result in an output of `2.756E+304`? For inputs of (say) 61 to 100, you shouldn't be getting anywhere near that value. The statement "Your program is attempting to calculate numbers that are out of the range of normal doubles" in this answer is simply incorrect for such input values. – Mark Dickinson Aug 13 '14 at 11:56
  • One example would be e^x where x = 703. The answer ends up being 4.091704141633894e+306 – drunkenmonkey44 Aug 13 '14 at 14:50
  • @drunkenmonkey44: Okay, that makes sense. I was misled by the original question, where you talked about an `xValue` of "61 or greater" causing problems. – Mark Dickinson Aug 13 '14 at 17:22