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") }, });

In reply to RE: De-engineer a number by ZZamboni
in thread De-engineer a number by KM

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.