[erlang-questions] How to calculate series expansion e^x

Guido Rumi <>
Wed Mar 4 00:32:05 CET 2015


I would change

fact(N) ->
  case N of
    0 -> 1;
    1 -> 1;
    _ -> N * fact(N - 1)
  end.

to

fact(N) ->
  fact_tr(N, 1).

fact_tr(N, Acc) ->
  case N of
    0 -> Acc;
    1 -> Acc;
    _ -> fact_tr   (N - 1, N * Acc)
  end.

To make it more efficient
http://stackoverflow.com/questions/33923/what-is-tail-recursion

On Tue, Mar 3, 2015 at 6:32 PM, Harit Himanshu <
> wrote:

> Richard and Alex
>
> Thanks a lot for your help. I got help up with my day job and could not
> try it out. Thanks a lot for your help on this problem.
> I tried a different version and it looks like following. Let me know if
> you see any issues with that
>
> -module(solution).
> -export([main/0]).
>
> main() ->
>   {ok, [N]} = io:fread("", "~d"),
>   Data = read_input([], N),
>   [io:format("~p~n", [e_x(X)]) || X <- Data].
>
> read_input(Input, N) ->
>   case N of
>     0 -> lists:reverse(Input);
>     _ -> {ok, [Num]} = io:fread("", "~s"),
>       {NumFloat, _} = string:to_float(Num),
>       read_input([NumFloat | Input], N - 1)
>   end.
>
> e_x(X) ->
>   1 + lists:sum([math:pow(X, N) / fact(N) || N <- lists:seq(1, 9)]).
>
> fact(N) ->
>   case N of
>     0 -> 1;
>     1 -> 1;
>     _ -> N * fact(N - 1)
>   end.
>
> On Wed, Feb 25, 2015 at 4:38 PM, Alex Alvarez <> wrote:
>
>>  Or just simply...
>>
>>
>> -module(e_fun).
>>
>> -export ([start/2]).
>>
>> start (N, X) ->
>>   1 + step (N - 1, 1, X, 1.0, 0).
>>
>> step (0, _, _, _, S) -> S;
>> step (N, NN, X, Z, S) ->
>>     ZZ = Z * X/NN,
>>   step (N - 1, NN + 1, X, ZZ, S + ZZ).
>>
>>
>> Here I'm just reusing the each previous term (ZZ) of the Taylor series to
>> compute the next term and then add it up to the sum (S).
>>
>> Cheers,
>> Alex
>>
>>
>>
>> On 02/24/2015 10:27 PM, Richard A. O'Keefe wrote:
>>
>> On 25/02/2015, at 11:00 am, Harit Himanshu <> <> wrote:
>>
>>
>>  I am trying to learn Functional Programming and Erlang by practicing problems available online.
>>
>> One question where I don't know about solving it is
>>
>> The series expansion of ex is given by:
>>
>> 1 + x + x2/2! + x3/3! + x4/4! + .......
>>
>> Evaluate e^x for given values of x, by using the above expansion for the first 10 terms.
>>
>>
>> The problem statement could be found here
>>
>> Can someone guide me how this could be achieved in Erlang?
>>
>>  The first 10 terms of exp(X) are
>>      X    X^2   X^3         X^9
>> 1 + --- + --- + --- + ... + ---
>>      1     2     6           9!
>> This is a polynomial.  We can evaluate it cheaply using
>> Horner's Rule.  Any time you have a polynomial to
>> evaluate, you should think about using Horner's Rule.
>>
>>      X     /     X    /      X        /      X  \   \ \
>> 1 + --- * | 1 + --- * | 1 + --- * ... | 1 + --- | ...| |
>>      1     \     2    \      3        \       9 /   / /
>>
>> We can see a building block here: 1 + (X/n)*Rest.
>>
>> So let's make a function for the building block:
>>
>> step(X, N, Rest)
>>   when is_float(X), is_float(N), is_float(Rest) ->
>>     1.0 + (X/N)*Rest.
>>
>> There are 9 steps, which is small enough to do by hand:
>> (NINE steps to get TEN terms.  I hope that's clear.)
>>
>> exp(X)
>>   when is_float(X) ->
>>     step(X, 1.0, step(X, 2.0, step(X, 3.0,
>>     step(X, 4.0, step(X, 5.0, step(X, 6.0,
>>     step(X, 7.0, step(X, 8.0, step(X, 9.0, 1.0))))))))).
>>
>>
>> I should point out that this is a lousy way to compute
>> exp(X) for abs(X) "large".  Waving hands vaguely, you
>> want X^10/10! "small".  The relative error for X = 1.0
>> is -1.1e-7, for X = 2.0 is -4.6e-5, and for X = 4.0 is
>> a scary -0.0081.
>>
>> One technique that's used in cases like this is
>> RANGE REDUCTION.  e^x = 2^(1.442695... * x).
>> To begin, scale x by log of e to the base 2,
>> and separate that into an integer part N and a fraction
>> part F.  e^x is then 2^(N+F) = 2^N*2^F.  Since F is
>> "small", we can use something like this polynomial.
>> And then we can use the equivalent of C's ldexp() to
>> handle the 2^N* part.  Or we could if Erlang _had_ an
>> equivalent of ldexp().
>>
>> You don't really need the is_float/1 tests; I put them in
>> so that the compiler could generate better native code.
>>
>> _______________________________________________
>> erlang-questions mailing ://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150303/33222a5a/attachment.html>


More information about the erlang-questions mailing list