Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: Rounding over numbers

by Athanasius (Archbishop)
on Feb 15, 2016 at 12:05 UTC ( [id://1155249]=note: print w/replies, xml ) Need Help??


in reply to Rounding over numbers

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.

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Rounding over numbers
by Laurent_R (Canon) on Feb 15, 2016 at 12:34 UTC
    That “epsilon” value of 1e-14 worries me! Common sense suggests that if a fudge factor is needed to some tests work when they should, then that same fudge factor will make other tests fail when it should’t. Or is this paranoia?
    This also worries me. I can't believe that this will solve the problem in all cases.
    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).
    It does not seem that BigRat, BigInt, BigNum and the like are doing that.

    But that is what Perl 6 is doing with the Rat type, which consists of a pair of integer numbers representing separately the numerator and the denominator, so that 13.25 would be represented as (1325, 100), or perhaps more probably (53, 4). I can't check right now, but maybe one of the Perl 6 modules (I mean the Perl 5 modules developed over the years to simulate and test the Perl 6 concepts) is doing that.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1155249]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2024-04-19 21:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found