# Calculate e^x and ln(x)

Given a floating point `x` (`x<100`), return `e^x` and `ln(x)`. The first 6 decimal places of the number have to be right, but any others after do not have to be correct.

You cannot have any "magic" constants explicitly stated (e.x. `a=1.35914` since `1.35914*2 ~= e`), but you can calculate them. Only use `+`, `-`, `*`, and `/` for arithmetic operators.

If x is less than or equal to 0, output `ERROR` instead of the intended value of ln(x).

Test Cases:

``````input: 2
output: 7.389056 0.693147
input: 0.25
output: 1.284025 -1.386294
input: 2.718281828
output: 15.154262 0.999999  (for this to output correctly, don't round to 6 places)
input: -0.1
output: 0.904837 ERROR
``````

Shortest code wins.

-
I assume you mean to exclude exponentiation of entirely (not just for the the calculation of e itself)? `2**(x*1.442695)` for example seems a bit too easy. – primo Nov 25 '12 at 18:04
@primo: yes, there is no exponentiation whatsoever, but things like `product([2]*3)` is ok. I guess I should rule out "magic constants" in the case of `1.442695`. – beary605 Nov 25 '12 at 18:35
You might want to also specify a valid range for the input - any approximation can lose accuracy if `x` becomes too large or too small. – arshajii Nov 26 '12 at 0:08
@A.R.S.: added a boundary. Thanks. – beary605 Nov 26 '12 at 0:14
No one uses APL!? Seriously? – TwiNight Dec 25 '12 at 19:45

## JavaScript, 103101999793 90

This implementation is based on primo's comprehensive description of the algorithm he used.

``````for(e=l=x=prompt(g=1e5);--g;y=x-1,l=(x>1?y/=x:-y)*l+y/g)
e=1+e/g*x;
``````

Edit:
- Trying to catch Perl. Stole a byte back from primo by copying his branch. :)
- 2 more bytes courtesy of primo.
- Finally, caught primo's version! With primo's help, of course... :)
- Simplified the assignment to L. Shaved 3 more bytes.

-
It's somewhat humorous that defining `Math.abs` inline is actually shorter than using the built-in. – primo Nov 27 '12 at 7:39
As far as catching perl goes, would it help if I pointed out that the initial values of `e` and `l` don't really matter? – primo Dec 2 '12 at 6:58
@primo Nice catch! – Paul Walls Dec 2 '12 at 8:13
I've got 93, by combining the `y` and `l` definitions: `l=(x>1?y=1-1/x:-(y=x-1))*l+y/g` – primo Dec 14 '12 at 7:29
Very elegant. I probably spent over an hour trying to figure out a way to exploit the relationship between `x<1` and `y<0`. You sir, are a genius! :) – Paul Walls Dec 14 '12 at 9:37

## PHP 109 107 bytes

``````<?for(\$g=1e4;--\$g;\$l=\$y/\$g+abs(\$y=\$x>1?1-1/\$x:\$x-1)*\$l)\$e=1+\$e/\$g*\$x.=fgets(STDIN);echo"\$e ",\$x>0?\$l:ERROR;
``````

is a fairly straight-forward calculation. I use a nested form of the sum of inverse factorials, which not only increases the convergence rate, but also allows for exponentiation at the same time:

is slightly more complicated. All convergent series seem to work for or , but not both (Newton's iteration does not have this limitation, but requires the calculation of each step). This isn't really a problem, though, given the log identity:

This means that if, for example, the iteration you're using only works on and , you can use the multiplicative inverse of and negate the result. Because I was using a nested identity for , I also chose to use a nested identity for :

where

Or equivalently, as demonstrated by Paul Walls' implementation:

I define the case as (which is necessarily negative), using the absolute value for the inner product, and then allowing a bare value in the fraction to correct the sign.

Sample I/O:

``````\$ echo 2 | php exp_ln.php
7.3890560989307 0.69314718055995

\$ echo 0.25 | php exp_ln.php
1.2840254166877 -1.3862943611199

\$ echo 2.718281828 | php exp_ln.php
15.154262234523 0.99999999983113

\$ echo -0.1 | php exp_ln.php
0.90483741803596 ERROR
``````

## Perl 9593 89 bytes

``````\$e=1+\$e/\$?*(\$x.=<>),\$l=\$_/\$?+\$l*abs,\$_=\$x>1?1-1/\$x:\$x-1while--\$?;print"\$e ",\$x>0?\$l:ERROR
``````

Nearly identical to the PHP solution above, with a slightly larger iteration (`65535` down to `0`).

Edits:

• Both 2 byte improvements due to Paul Walls.
• Four more bytes saved in Perl by (ab)using `\$?`, which is stored internally as an unsigned short, and by using `\$_` to save parentheses in `abs`.
-
+1 lovely explanation – DavidC Nov 26 '12 at 12:13
For x = 1e-4, I get php "1.0001000050002 -8.9909564381939" and perl "1.00010000500017 -8.99099322429857". Should be like "1.000100005 -9.21034037195" Anyways nice job taking advantage of ln x = -ln 1/x to use a nested expression – miles Nov 26 '12 at 13:49
@milest `x=1e-5` will be off by even more, because it's the same calculation as `x=100000`. As it is, `x=1e-2` and `x=100` are accurate to full floating point precision, and `x=1e-3` and `x=1000` are accurate to about 5 digits. If more accuracy is needed, the arbitrary `1e4` bound that I've chosen can be increased accordingly. – primo Nov 26 '12 at 14:25

## Python 2 (168 char)

basic implementation of power series

I need to learn a golfing language =/

I increased the bound to 1e-14 (twice from 1e-7) since some values were off a bit in 6 decimal places, works well for input from 1e-5 to 100 (slows down at input approaches 0)

``````x=input();t,r,i=1,0,1.
while abs(t)>=1e-14:t,r,i=t*x/i,r+t,i+1
if x<=0:s='Error'
else:z=(x-1.)/(x+1);t,s,i=2*z,0,1
while abs(t/i)>=1e-14:t,s,i=t*z*z,s+t/i,i+2
print r,s
``````
-
Doesn't python support `m=1e-7`? – dmckee Nov 25 '12 at 20:53
yes it does but 1e-7 can be thought of as 1*10^-7 which might be thought of as exponentiation, so I'm not really sure if its allowed here – miles Nov 25 '12 at 20:59
I will allow for scientific notation. – beary605 Nov 26 '12 at 0:02

## Haskell, 166 (89 without I/O)

``````s=1e-7
e x|x>s=1/e(-x)|x>0=1+x|y<-e\$x+s=y-y*s
l x|x<1=0-l(1/x)|1>0=sum\$map(s/)[1,1+s..x]
n x|x<0="ERROR"|1>0=show\$l x
``````

Takes an alternative approach: we use that

∂/∂x ex = ex

and solve the differential equation numerically, with a simple euler method. Similarly, use

ln x = 1x 1/x d‌x

and calculate the integral with the rectangular method.

Example:

\$ echo 2 | ./exp-and-log
7.389056835370484 0.6931472554471929
\$ echo 0.25 | ./exp-and-log
1.284025432730133 -1.3862944228194163
\$ echo 2.718281828 | ./exp-and-log
15.15426430695358 1.0000000576151333
\$ echo -0.1 | ./exp-and-log
0.9048374135134576 ERROR

It's quite amazingly inefficient, in fact it uses about 4 GB of memory even for these examples (since it's non-tail–recursive... you need to compile (in GHC) with `-with-rtsopts=-K2G` so it even accepts such a ridiculous stack size).

-

Surprised at no one using APL which has built-in exponentiation and natural logarithm, I will submit one.

``````(*x),⍟x←⎕
``````
-
`Only use +, -, *, and / for arithmetic operators.`? – beary605 Dec 27 '12 at 17:12
Oh didn't see that! Was falling back to Taylor expansion (which I thought would still favor APL due to built-in factorial, reciprocal and polynomial functions) when I found out the `⊥` function breaks when calculating `e^99` using 154 terms 'cuz `99^154>2^1024`. Given up – TwiNight Dec 27 '12 at 18:27