Skip Menu |
Report information
Id: 128820
Status: resolved
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: zefram [at] fysh.org
Cc:
AdminCc:

Severity: (no value)
Tag: Bug
Platform: (no value)
Patch Status: (no value)
VM: (no value)



From: Zefram <zefram [...] fysh.org>
To: rakudobug [...] perl.org
Subject: [BUG] == on Num literals produces bogus answer
Date: Tue, 2 Aug 2016 18:55:20 +0100
Download (untitled) / with headers
text/plain 894b
Show quoted text
> 1180591620717411303424e0 == 1180591620717409992704e0
True Show quoted text
> 1180591620717411303424e0 === 1180591620717409992704e0
True Say what? These are distinct Num values, differing by 10 ulp. These literals work fine in other contexts: Show quoted text
> my $a = 1180591620717411303424e0
1.18059162071741e+21 Show quoted text
> my $b = 1180591620717409992704e0
1.18059162071741e+21 Show quoted text
> $a.Int
1180591620717411303424 Show quoted text
> $b.Int
1180591620717409992704 Show quoted text
> $a == $b
False Show quoted text
> $a === $b
False == and === give the right result when applied to $a and $b as here, or when applied to declared constants ("constant \A = 118..."). They also work fine when comparing a variable against a literal. They go wrong when applied directly to two literal expressions. They also go wrong with some more complex expressions that bring in both values as literals, such as if both sides are multiplied by 1.0e0 or by a variable containing that value. -zefram
From: "Patrick R. Michaud" <pmichaud [...] pobox.com>
To: perl6-compiler [...] perl.org
Subject: Re: [perl #128820] [BUG] == on Num literals produces bogus answer
Date: Tue, 2 Aug 2016 13:42:02 -0500
On Tue, Aug 02, 2016 at 10:55:34AM -0700, Zefram wrote: Show quoted text
> These literals work fine in other contexts: >
> > my $a = 1180591620717411303424e0
> 1.18059162071741e+21
> > my $b = 1180591620717409992704e0
> 1.18059162071741e+21
> > $a.Int
> 1180591620717411303424
> > $b.Int
> 1180591620717409992704
> > $a == $b
> False
> > $a === $b
> False
It's not universally true that Num literals like these "work fine in other contexts" -- the pair of literals in the example given "work" because they differ in the fifteenth decimal digit of precision. This is within the acceptable norms for Num (floating point) precision. Choosing a different pair of literal values that differ beyond the first 15 digits of precision shows that things do not work fine in other contexts: Show quoted text
> my $a = 1180591620717411303424e0
1.18059162071741e+21 Show quoted text
> my $b = 1180591620717411333333e0
1.18059162071741e+21 Show quoted text
> $a.Int
1180591620717411303424 Show quoted text
> $b.Int
1180591620717411303424 Show quoted text
> $a == $b
True Show quoted text
> $a === $b
True In short, it's "normal" (expected behavior) for mathematical errors to occur beyond 15 digits of precision in Num (floating point) values. Pm
To: "Patrick R. Michaud via RT" <perl6-bugs-followup [...] perl.org>
Date: Tue, 2 Aug 2016 20:01:42 +0100
Subject: Re: [perl #128820] [BUG] == on Num literals produces bogus answer
From: Zefram <zefram [...] fysh.org>
Download (untitled) / with headers
text/plain 1.7k
Patrick R. Michaud via RT wrote: Show quoted text
>It's not universally true that Num literals like these "work fine >in other contexts" -- the pair of literals in the example given "work" >because they differ in the fifteenth decimal digit of precision.
Once again, you're mistakenly supposing my complaint to be from a decimal point of view and the problem explained by rounding in the decimal->float conversion. This is not the case. Both of my literals directly represent values that are exactly representable in floating point, and in most contexts they correctly yield Nums with those values. Show quoted text
>In short, it's "normal" (expected behavior) for mathematical errors to >occur beyond 15 digits of precision in Num (floating point) values.
It is not normal for the same literal to represent two different values when used twice. The decimal->float rounding doesn't account for this. More information: upon further experimentation, it seems that the critical issue is whether the two literals are compiled together. Any expression containing both literals has them actually yield the same value, and it's the proper value of whichever literal came first: Show quoted text
> (1180591620717411303424e0, 1180591620717409992704e0).map(*.Int)
(1180591620717411303424 1180591620717411303424) Show quoted text
> (1180591620717409992704e0, 1180591620717411303424e0).map(*.Int)
(1180591620717409992704 1180591620717409992704) Show quoted text
> ("1180591620717411303424e0", "1180591620717409992704e0").map(*.EVAL.Int)
(1180591620717411303424 1180591620717409992704) Perhaps the compiler is coalescing the constants based on them having identical .WHICH values, for which see [perl #128819]. The expression "2e0**70" doesn't get the same treatment, so the coalescing can't be happening after constant folding, if that gets folded. -zefram
Date: Fri, 19 Aug 2016 22:46:43 +0100
From: Zefram <zefram [...] fysh.org>
Subject: Re: [perl #128820] [BUG] == on Num literals produces bogus answer
To: "Patrick R. Michaud via RT" <perl6-bugs-followup [...] perl.org>
Download (untitled) / with headers
text/plain 118b
Additional: this also happens with Complex literals, where the real or imaginary parts suffer this as Nums. -zefram
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 1.5k
On Tue, 02 Aug 2016 10:55:34 -0700, zefram@fysh.org wrote: Show quoted text
> > 1180591620717411303424e0 == 1180591620717409992704e0
> True
> > 1180591620717411303424e0 === 1180591620717409992704e0
> True > > Say what? These are distinct Num values, differing by 10 ulp. > These literals work fine in other contexts: >
> > my $a = 1180591620717411303424e0
> 1.18059162071741e+21
> > my $b = 1180591620717409992704e0
> 1.18059162071741e+21
> > $a.Int
> 1180591620717411303424
> > $b.Int
> 1180591620717409992704
> > $a == $b
> False
> > $a === $b
> False > > == and === give the right result when applied to $a and $b as here, or > when applied to declared constants ("constant \A = 118..."). They also > work fine when comparing a variable against a literal. They go wrong when > applied directly to two literal expressions. They also go wrong with some > more complex expressions that bring in both values as literals, such as if > both sides are multiplied by 1.0e0 or by a variable containing that value. > > -zefram
Thank you for the report. This is now fixed. Fix: https://github.com/MoarVM/MoarVM/commit/067c0594103a025 https://github.com/MoarVM/MoarVM/commit/8841c4241b4faa8 https://github.com/MoarVM/MoarVM/commit/af2eb8a7f7d4344 https://github.com/MoarVM/MoarVM/commit/4d3fc2818d0032b https://github.com/rakudo/rakudo/commit/8422d7b4e23678b https://github.com/rakudo/rakudo/commit/a2a2a745c4242d1 Test: https://github.com/perl6/roast/commit/52c60ce5c283dd5b8 https://github.com/perl6/roast/commit/bba5e9fdda431c9f4


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org