in reply to Re: Numeric Comparisons Randomly Giving the Wrong Result
in thread Numeric Comparisons Randomly Giving the Wrong Result

Is using the integer pragma such a good idea? From the documentation:
1. use integer; 2. $x = 10/3; 3. # $x is now 3, not 3.33333333333333333

If only addition and subtraction are being used, should be fine - if other arithmetic operations are happening, wouldn't that result in a loss of precision?

Replies are listed 'Best First'.
Re^3: Numeric Comparisons Randomly Giving the Wrong Result
by Corion (Patriarch) on Sep 30, 2010 at 13:43 UTC

    Only if your units are not whole, indivisable units already. If you do all your calculations in cents and do not allow sub-cent amounts, then you won't need to care about rounding.

    If you do fancy calculations, like repeatedly adding fractional parts of things, you need to give deep thought to all your calculations anyway, whether they are in floating point or integer numbers.

      What about this situation - assuming you can get a large loan in Galactic Credits, at 0% APR, for a year:
      use strict; use warnings; use diagnostics; my $amount = 1e9; my $months = 12; my $repayment = $amount/$months; print "Monthly repayment = $repayment\n"; use integer; $repayment = $amount/$months; print "Monthly repayment = $repayment\n";

      prints out:

      Monthly repayment = 83333333.3333333
      Monthly repayment = 83333333
      

      which is not the same thing!

      On a different, but related note, increasing the loan to 1e12 Galactic Credits, gives this:

      Monthly repayment = 83333333333.3333
      Monthly repayment = 0
      

      That's because the loan amount is too big to hold in an integer (on my machine anyway):

      perl -le'use POSIX;print for SHRT_MAX, INT_MAX, LONG_MAX, FLT_MAX, DBL +_MAX;' 32767 2147483647 2147483647 3.40282346638529e+38 1.79769313486232e+308

      So use the integer pragma with caution!

        If you do fancy calculations, like repeatedly adding fractional parts of things, you need to give deep thought to all your calculations anyway, whether they are in floating point or integer numbers.

        I don't see where that part of my statement collides with your example.

        Sure, but the point is that altho you see a number ending with ".33333" printed out, it may not have that exact value in memory, and if further calculations are performed, that could become apparent. Similarly, of course, decimal numbers cannot truly represent the fraction 1/3. The "galactic credits" example is a bit disingenuous -- when was the last time you wrote a check for $833.3333 to pay your mortgage? Again, money has a fixed precision of two decimal places and needs to be kept there. If rounding is an issue, use tenths of a cent as an integer unit and write a rounding function. This could be as simple as >=/< 5, since integers are round down (so what would have been 4.9999999 tenths of a cent will be 4, anything more will be five).

        If you think it is more appropriate to round up (the bank wants at least what it is owned, ie, $8.34) you should still limit the precision with integers, otherwise you will end up with numbers like 1000.00000001 due to the floating point issues that motivated the original post, and if those are rounded up and collated you could be looking at whole dollars of error.