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

zxq9 <>
Wed Mar 4 00:59:00 CET 2015


Mostly a point of style, perhaps, but I think matching in the function head in 
this case is a bit more readable (it may also wind up being more efficient). 
This is more what I would expect to see in an Erlang program:

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

fact(0, Acc) -> Acc;
fact(1, Acc) -> Acc;
fact(N, Acc) -> fact(N - 1, N * Acc).

On 2015年3月3日 火曜日 20:32:05 Guido Rumi wrote:
> 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



More information about the erlang-questions mailing list