Sometimes, especially with Informix, I woud be given numbers in engineering notation, rather than a regular digit as I expected. I needed a quick way to make the e-notation more readable. This snippet is what I generally use to do this.
# This is the important line # s/([\.\d]+)e([-+]?\d+)/$1*10**$2/egi sub de_engineer { my $val = shift; $val =~ s/([\.\d]+)e([-+]?\d+)/$1*10**$2/egi; return $val; }

Replies are listed 'Best First'.
RE: De-engineer a number
by ZZamboni (Curate) on May 25, 2000 at 17:18 UTC
    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") }, });
      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).
RE: De-engineer a number
by perlmonkey (Hermit) on May 25, 2000 at 11:09 UTC
    Probably overkill. Perl understands the e notation already.
    $a = 5.6e3; print $a , "\n"; #or $a = '5.6e3'; $b = eval($a); print "$a == $b\n";
    Results:
    5600
    5.6e3 == 5600
      Overkill? It is a neat regex, that was the point. The point wasn't to find the best way to do it, but a cool, fun way.

      Cheers,
      KM