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;
\$e^x\$ 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:
$$e^x = 1 + x \left( 1 + \frac x 2 \left( 1 + \frac x 3 \left( 1 + \frac x 4 \bigg( 1 + \dots \bigg)\right)\right)\right)$$
\$\ln x\$ is slightly more complicated. All convergent series seem to work for \$x \le 1\$ or \$x \ge 1 \$, but not both (Newton's iteration does not have this limitation, but requires the calculation of \$e^{x_n}\$ each step). This isn't really a problem, though, given the log identity:
$$\ln x = -\ln \frac 1 x$$
This means that if, for example, the iteration you're using only works on \$0 < x \le 1\$ and \$x > 1\$, you can use the multiplicative inverse of \$x\$ and negate the result. Because I was using a nested identity for \$e^x\$, I also chose to use a nested identity for \$\ln x\$:
$$\ln(1 + x) = x\left(1 - x\left(\frac 1 2 - x\left(\frac 1 3 - x\left(\frac 1 4 - \dots \right)\right)\right)\right)$$
where \$0 < x \le 1\$
Or equivalently, as demonstrated by Paul Walls' implementation:
$$\ln(1 + x) = x - x\left(\frac x 2 - x\left(\frac x 3 - x\left(\frac x 4 - \dots \right)\right)\right)$$
I define the \$0 < x \le 1\$ case as \$x-1\$ (which is necessarily negative), using the absolute value for the inner product, and then allowing a bare \$x\$ 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 95 93 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
.
2**(x*1.442695)
for example seems a bit too easy. \$\endgroup\$product([2]*3)
is ok. I guess I should rule out "magic constants" in the case of1.442695
. \$\endgroup\$x
becomes too large or too small. \$\endgroup\$