http://qs321.pair.com?node_id=652437

in reply to Exponential Function Programming

I think that this is more noble and incomprehensible :>)
```#!/usr/bin/perl
use strict;
use warnings;
sub exp_ {
my \$x = shift;
my (\$d, \$ret, \$i) = (1.0, 1);
while (\$ret - \$d != \$ret) {
\$d *= \$x/++\$i;
\$ret += \$d;
}
return \$ret;
}
for (1..100) {
print "exp(\$_) = ".exp_(\$_)."\n";
}

Replies are listed 'Best First'.
Re^2: Exponential Function Programming
by ikegami (Patriarch) on Nov 22, 2007 at 20:21 UTC
\$ret - \$d != \$ret is interesting. One would think it's the same as \$d (in boolean context), but it isn't. By testing the effect of \$d (\$ret - \$d != \$ret) instead of \$d itself, the loop can be ended sooner.
```my \$ret = 1;

for my \$d (1e-15, 1e-20) {
printf("%g %d %d\n",
\$d,
( \$d              )?1:0,
( \$ret-\$d != \$ret )?1:0,
);
}
```1e-015 1 1   # Often equivalent.
1e-020 1 0   # But not when there's an underflow.
Of course, underflow behaves friendly in this case. But my prime goal was to demonstrate no necessity for evaluating both factorial and power in each loop.

But such a demonstrations wasn't necessary for me since I had finished writing the following from scratch before you posted your solution. (I didn't post it since I didn't want to do the OP's homework for him.)

```sub ikegami_exp {
my (\$x) = @_;
my \$last   = 0;
my \$result = 1;
my \$acc    = 1;
for (my \$n = 1; abs(\$result-\$last)>0; \$n++) {
\$last = \$result;
\$acc *= \$x/\$n;
\$result += \$acc;
}
return \$result;
}

for (1, 0.1, 10, 3.14, 0.1234, 100) {
printf("%.16e: exp() = %.16e  ikegami_exp() = %.16e\n",
\$_,
exp(\$_),
ikegami_exp(\$_),
);
}