[erlang-questions] How to calculate series expansion e^x
Harit Himanshu
<>
Wed Mar 4 00:42:00 CET 2015
Thanks Guido, That is more useful.
On Tue, Mar 3, 2015 at 3:32 PM, 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
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150303/5a4d9b11/attachment.html>
More information about the erlang-questions
mailing list