0

I'm writing a script that calls a function get_fact to calculate Euler's number to 10 decimal places. My function is:

function [ nfactorial ] = get_fact( n )
%input a non-negative integer
%output is factorial of that integer
for i=0:n
    nfactorial=prod(1:n);
end
end

I now want to calculate Euler's number by having n loop from 0 to infinity and taking the sum of 1/get_fact(i).

How would I write the break in order to stop loop at the 10th decimal place? I am not allowed to use Euler's number in my script.

So far I have:

for i = 0:inf
    prod((1/ get_fact(i)))
end

but this is an infinite series.

I was thinking of using

if prod((1/ get_fact(i))) > 1E-10
break
end

but I'm not sure if this is the right way to go about the problem.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
rubisco_
  • 63
  • 1
  • 7
  • Use a `while` loop instead with something like `while prod((1/ get_fact(i))) > 1E-10` – Adriaan Oct 10 '15 at 20:01
  • `1 / get_fact(i)` is a scalar value not a vector, so `prod(1 / get_fact(i))` will also be the exact same value as `1 / get_fact(i)` and won't converge to `e`. Also `prod((1/ get_fact(i))) > 1E-10` is wrong and won't tell you that you have computed `e` to 10 decimal places of accuracy it will only tell you that the value of `prod((1/ get_fact(i))) > 1E-10` is greater than `1e-10`. – IKavanagh Oct 10 '15 at 20:01
  • `while prod((1/ get_fact(i))) > 1E-10` will only tell me if it is greater than `1e-10` like the other commenter said. – rubisco_ Oct 10 '15 at 20:07
  • Please consider accepting the other answers to your questions. It goes a long way and motivates more people to answer your questions. http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – rayryeng Oct 10 '15 at 21:37

1 Answers1

2

Firstly I would rewrite your function for finding the factorial to the simpler

function n = factorial(n)
    n = prod(1:n);
end

The loop in your question is unnecessary as you never use the loop variable i. I wouldn't use this function though for my solution as it can be quite slow because you have to compute redundant information at each loop iteration.

If you still want to use a for loop you need to rewrite it to

function f = factorial(n)
    f = 1; % 0 factorial
    for i = 1:n
        f = f * i;
    end
end

You can use the natural logarithm and the rules of logs to determine a very accurate value of e with which you can compare against. The value of e you can check against is given by x^(1 / log(x)) where x can be any positive real number other than 1, like 2. We can see this in

                                                                Rules of logs

Now how do we check that we've computed a value of e to 10 decimal places of accuracy. Well given that b from above is a very accurate representation of e we can compare against it to determine when we've reached an accurate solution

x = 2; % Any positive number other than 1
c = x^(1 / log(x));
...
if (abs(e - c) < 1e-10)
    break;
end

In my solution e is the approximate value I've computed with the infinite sum. Note: the absolute value is taken to prevent false positives when e - c is a negative number.


Now, an efficient method for computing the infinite sum. We can exploit how the factorial is computed to not have to compute it during each iteration hugely improving the efficiency. Firstly, we need a sum variable, e in my case, to keep track of our approximate solution. Then we need another variable to keep track of the factorial, f in my case. As 0 is a funny case we'll start off with it

e = 0;
f = 1; % 0 factorial

e = e + 1 / f;

and now we have the first element in our infinite sum. Next we can use the infinite sum to compute a more accurate approximate to e. The factorial can be updated during each iteration with f = f * n; leading to

for n = 1:inf
    f = f * n; % Compute new factorial
    e = e + 1 / f; % Infinite sum
    ...
end

Now putting that altogether produces

x = 2; % Any positive number other than 1
c = x^(1 / log(x));

e = 0;
f = 1; % 0 factorial

e = e + 1 / f;

for n = 1:inf
    f = f * n; % Compute new factorial
    e = e + 1 / f; % Infinite sum
    if (abs(e - c) < 1e-10)
        break;
    end
end
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
  • I am supposed to use a for loop to calculate the factorial, which is why I did it that way. I am getting a warning for the script however: Warning: FOR loop index is too large. Truncating to 9223372036854775807. > In testing (line 9) How would I correct this? – rubisco_ Oct 10 '15 at 21:22
  • And I also want to call my get_fact function in the script – rubisco_ Oct 10 '15 at 21:26
  • By using `9223372036854775807` instead of `inf`. MATLAB can't loop to infinity it can only loop until `9223372036854775807`. However, its just a warning so you can safely ignore it. Your `get_fact` function is wrong then. The `for` loop is useless. You never use `i` and you overwrite `nfactorial` during each iteration. My solution also still computes the factorial with a `for` loop it just does it more accurately. – IKavanagh Oct 10 '15 at 21:26
  • @rubisco_ I've edited my answer to include a **correct** function for computing the factorial with a `for` loop. If you want to call this in the script replace `f = f * n` with `f = factorial(n);`. – IKavanagh Oct 10 '15 at 21:30
  • thank you, how do I now get it to display 10 decimals. I know `format long` displays to 15. – rubisco_ Oct 10 '15 at 21:49
  • Glad to have been of help! Feel free to [accept my answer](http://meta.stackexchange.com/q/5234) if you feel it was useful to you. :-) – IKavanagh Oct 10 '15 at 21:51
  • `fprintf(1, '%.10f\n', e);` – IKavanagh Oct 10 '15 at 21:52