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...

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.