[prev in list] [next in list] [prev in thread] [next in thread] 

List:       perl5-porters
Subject:    Re: [perl #125266] Unexpected interaction between binary multiplication operator and  Test::More::cm
From:       Zefram <zefram () fysh ! org>
Date:       2015-05-28 14:51:52
Message-ID: 20150528145152.GE23010 () fysh ! org
[Download RAW message or body]

James E Keenan wrote:
>Today I was bitten by an unexpected interaction between Perl's binary
>multiplication operator (*) and Test::More::cmp_ok().

It's nothing to do with cmp_ok, and little to do with *; it's just
floating point rounding, specifically on conversion from decimal to
floating point.  0.21 does not have a terminating binary representation,
nor does 1.68, so in general you can't expect to get exact results.
It's not in general surprising that floating point computations produce
such mathematical discrepancies.  The only strange bit is that the result
changed between Perl versions:

$ perl5.8.0 -lwe 'printf "%.70f\n" x 2, 1.68, 8 * 0.21' 
1.6799999999999999378275106209912337362766265869140625000000000000000000
1.6799999999999999378275106209912337362766265869140625000000000000000000
$ perl5.8.1 -lwe 'printf "%.70f\n" x 2, 1.68, 8 * 0.21'
1.6800000000000001598721155460225418210029602050781250000000000000000000
1.6799999999999999378275106209912337362766265869140625000000000000000000

Both versions agree on the floating point conversion of 0.21, and indeed
have the NV whose value is closest to 0.21.  Both correctly multiply that
converted value by 8, which is an exact computation in floating point.
Where they disagree is on the direct floating point conversion of 1.68.
As you can see, 5.8.0 and below have picked the NV closest to 1.68,
thus agreeing with the conversion of 0.21.  But 5.8.1 and above have
picked the NV the other side of 1.68, which is less close and disagrees
with the conversion of 0.21.

We already know the decimal->float conversion is broken; see [perl
#41202].  Interestingly, that ticket's test case also shows a change
from correctly-rounded conversion to incorrect between 5.8.0 and 5.8.1:

$ perl5.8.0 perl -lwe 'printf "%f\n", 1180591620717411303424.0'
1180591620717411303424.000000
$ perl5.8.1 perl -lwe 'printf "%f\n", 1180591620717411303424.0'
1180591620717411172352.000000

So I suspect that the dodgy conversion of 1.68 is merely another example
of [perl #41202].

-zefram
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic