[erlang-questions] How to calculate series expansion e^x
zxq9
zxq9@REDACTED
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 <
>
> harit.subscriptions@REDACTED> 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 <eajam@REDACTED> 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
<harit.subscriptions@REDACTED> <harit.subscriptions@REDACTED> 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
> >> listerlang-questions@REDACTED://erlang.org/mailman/listinfo/erlang
> >> -questions
> >>
> >>
> >>
> >> _______________________________________________
> >> erlang-questions mailing list
> >> erlang-questions@REDACTED
> >> http://erlang.org/mailman/listinfo/erlang-questions
> >
> > _______________________________________________
> > erlang-questions mailing list
> > erlang-questions@REDACTED
> > http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list