in reply to De-engineer a number

Three other techniques come to mind:
$val=$val+0; # Sum $val=eval "$val"; # Eval $val=sprintf("%f", $val); # Sprintf # Call your original technique "Regex"
Experimenting with the four techniques (using the subroutines defined in the code below) shows that none of them is perfect. This is because Sum, Regex and Eval ultimately rely on how Perl interprets the resulting number. And perl sometimes will return scientific notation, so in those cases Sum, Regex and Eval will return exactly the same number. For example:
Sum("1.25e-5") gives '1.25e-05' Regex("1.25e-5") '1.25e-05' Eval("1.25e-5") '1.25e-05' Sum("1.25e-3") 0.00125 Regex("1.25e-3") 0.00125 Eval("1.25e-3") 0.00125
So you can see that whenever perl would return scientific notation, these three methods return the same number. Now, using Sprintf:
Sprintf("1.25e-5") 0.000013 Sprintf("1.25e-3") 0.001250 Sprintf("1.25e-7") 0.000000
This method always expands the number, but its disadvantage is that it always returns a fixed number of digits. Of course, you can always use something like:
sprintf("%.10f", $val) 0.0012500000
Which gives you the trailing zeros. So finally you can use something like the SprintfSubst function below, which uses sprintf with a large precision and then eliminates the trailing zeros.

The performance figures for the script below on my Ultra 1 are:

Benchmark: timing 100000 iterations of Eval, Regex, Sprintf, SprintfSu +bst, Sum... Eval: 20 wallclock secs (19.58 usr + 0.00 sys = 19.58 CPU) Regex: 9 wallclock secs ( 9.97 usr + 0.00 sys = 9.97 CPU) Sprintf: 7 wallclock secs ( 6.22 usr + 0.00 sys = 6.22 CPU) SprintfSubst: 8 wallclock secs ( 8.74 usr + 0.00 sys = 8.74 CPU) Sum: 4 wallclock secs ( 3.52 usr + 0.00 sys = 3.52 CPU)
Sum is by far the fastest, so if you are dealing with "normal" (not too small, not too large) numbers, that's the best way to go. Regex, Sprintf and SprintfSubst are very close together, and SprintfSubst is the one that works with any number.

Just some food for thought :-)

--ZZamboni


Here's the code used above:
#!/usr/bin/perl use Benchmark; sub Regex { my $val=shift; $val =~ s/([\.\d]+)e([-+]?\d+)/$1*10**$2/egi; return $val; } sub Eval { my $val=shift; $val=eval " $val "; return $val; } sub Sum { my $val=shift; $val=$val+0; return $val; } sub Sprintf { my $val=shift; $val=sprintf("%f",$val); return $val; } sub SprintfSubst { my $val=shift; $val=sprintf("%.10f", $val); $val=~s/0*$//; return $val; } timethese(100000, { Regex => sub { Regex("1.25e-3") }, Eval => sub { Eval("1.25e-3") }, Sum => sub { Sum("1.25e-3") }, Sprintf => sub { Sprintf("1.25e-3") }, SprintfSubst => sub { SprintfSubst("1.25e-3") }, });

Replies are listed 'Best First'.
RE: RE: De-engineer a number
by perlmonkey (Hermit) on May 25, 2000 at 22:22 UTC
    This is pretty cool ZZamboni. The sum is clever.

    KM: I didnt mean to imply that your regex was not neat. I just wanted to make sure you and everyone else reading knew that perl could handle scientific notation without the regex (as ZZamboni has superbly demonstrated).