I’ve been thinking over this question in light of the notorious floating-point problems highlighted by kevbot and Laurent_R above. It does seem that kevbot’s recourse to Number::Format is the better option. Here’s the relevant code from the round subroutine in that module (omitting parameter checks, negative number handling, etc.):
sub round
{
my ($self, $number, $precision) = ...;
...
my $multiplier = (10 ** $precision);
my $result = abs($number);
my $product = $result * $multiplier;
...
# We need to add 1e-14 to avoid some rounding errors due to the
# way floating point numbers work - see string-eq test in t/round.
+t
$result = int($product + .5 + 1e-14) / $multiplier;
...
return $result;
}
This is, I think, the correct approach. But it still leaves me wondering...
- Since $result is returned as a floating point number (generated by a division operation), isn’t there still the possiblity that it will be slightly lower than it should be? In which case, the accuracy of the call could in part depend on the way the return value is used by the calling code?
- That “epsilon” value of 1e-14 worries me! Common sense suggests that if a fudge factor is needed to make some tests work when they should, then that same fudge factor will make other tests fail when they shouldn’t. Or is this paranoia?
I’m thinking the only foolproof method may be to avoid the use of floating-point numbers altogether by doing the calculation with integers, and inserting the decimal point only when the calculation is complete. Is there a module which takes this approach? So far, I haven’t found one (but I may well be looking in the wrong places).
Any ideas?
Update: Corrected typos in the second bullet point.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.
|