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

Owner: Nobody
Requestors: sisyphus <sisyphus1 [at] optusnet.com.au>
victor.adam [at] derpymail.org
Cc:
AdminCc:

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



Subject: Floating point anomalies
From: <sisyphus1 [...] optusnet.com.au>
Date: Wed, 11 Oct 2017 22:01:38 +1100
To: <rakudobug [...] perl.org>
Download (untitled) / with headers
text/plain 925b
Hi, Some anomalous rounding behaviour on Ubuntu-16.04 was noted at http://www.perlmonks.org/?node_id=1200326 Here are the specifics: $ perl6 --version This is Rakudo version 2017.07 built on MoarVM version 2017.07 implementing Perl 6.c. ======= Issue 1 ======= $ perl6 -e 'say Int(2e25);' 20000000000000001811939328 $ perl6 -e 'say Int(20e24);' 19999999999999997516972032 That seems odd because 2e25 and 20e24 are exactly equivalent. ======= Issue 2 ======= $ perl6 -e 'say "WTF" if 1.000000000000001e0 == 1e0;' WTF That seems odd because 1.000000000000001e0 and 1e0 are quite different double precision values. According to perl5: $ perl -le 'print scalar reverse unpack "h*", pack "d<", 1.000000000000001e0;' 3ff0000000000005 $ perl -le 'print scalar reverse unpack "h*", pack "d<", 1e0;' 3ff0000000000000 Is it the intention of the perl6 developers that such discrepancies will be addressed ? Cheers, Rob
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 740b
On Wed, 11 Oct 2017 04:25:32 -0700, sisyphus wrote: Show quoted text
> > Is it the intention of the perl6 developers that such discrepancies will be > addressed ?
Eventually, yes. A bit lower on the priorities list at the moment, though. What you describe looks to be similar to the other issue I have in my private bug stash: say .1e0 + .2e0 == .3e0; # False say 1.0e-1 + 2.0e-1 == 3.0e-1; # True; And a brief look into guts suggests it's to do with the way our Nums are constructed during parsing. I was able to repro the issue with the C version of what we do in our Grammar: https://glot.io/snippets/eufyogt02g So yeah, the plan is to eventually address these. If you spot any more inconsistencies and weirdness, please report them.
Date: Thu, 12 Oct 2017 20:31:33 +1100
To: <perl6-bugs-followup [...] perl.org>
Subject: Re: [perl #132268] Floating point anomalies
From: <sisyphus1 [...] optusnet.com.au>
Download (untitled) / with headers
text/plain 1.8k
Show quoted text
-----Original Message----- From: Zoffix Znet via RT Sent: Wednesday, October 11, 2017 11:09 PM To: sisyphus1@optusnet.com.au Subject: [perl #132268] Floating point anomalies
> What you describe looks to be similar to the other issue I have in my > private bug stash: > > say .1e0 + .2e0 == .3e0; # False > say 1.0e-1 + 2.0e-1 == 3.0e-1; # True; > > And a brief look into guts suggests it's to do with the way our Nums are > constructed during parsing. I was able to repro the issue with the C > version of what we do in our Grammar: https://glot.io/snippets/eufyogt02g
Yes, the anomaly with those particular values lies in the assignment of .3e0 versus the assignment of 3.0e-1. Looks like it's the difference between calculating 3 * 0.1 and 30 * 0.01: $ perl -le 'print scalar reverse unpack "h*", pack "d<", 3 * 0.1;' 3fd3333333333334 $ perl -le 'print scalar reverse unpack "h*", pack "d<", 30 * 0.01;' 3fd3333333333333 At least, the calculation of 3.0e-1 produces produces the first value (which is overstated by one ULP), and the calculation of 0.3e0 produces the second (which is correct).
> So yeah, the plan is to eventually address these.
That's good news.
> If you spot any more inconsistencies and weirdness, please report them.
Perl6's printf() function looks a little suspect - though I might be missing something here. As with perl5's say function, doubles are rounded to 14 decimal digits of precision, so we get: $ perl6 -e 'say 1.000000000000001e0;' 1 $ perl -E 'say 1.000000000000001e0;' 1 On perl5 we can get to see a more accurate rendition of the base 10 value using printf(): $ perl -e 'printf "%.16e\n", 1.000000000000001e0;' 1.0000000000000011e+000 But that doesn't work on perl6: $ perl6 -e 'printf "%.16e\n", 1.000000000000001e0;' 1.0000000000000000e+00 Is there something amiss here ? Cheers, Rob
Subject: Re: [perl #132268] Floating point anomalies
From: Brandon Allbery <allbery.b [...] gmail.com>
Date: Thu, 12 Oct 2017 13:15:06 -0400
To: sisyphus1 [...] optusnet.com.au
CC: Carl Mäsak via RT <perl6-bugs-followup [...] perl.org>
Download (untitled) / with headers
text/plain 977b
On Thu, Oct 12, 2017 at 5:31 AM, <sisyphus1@optusnet.com.au> wrote:
Show quoted text
Perl6's printf() function looks a little suspect - though I might be missing
something here.

As with perl5's say function, doubles are rounded to 14 decimal digits of
precision, so we get:

$ perl6 -e 'say 1.000000000000001e0;'
1

$ perl -E 'say 1.000000000000001e0;'
1

On perl5 we can get to see a more accurate rendition of the base 10 value

I question your use of 'accurate'. The low bits are *never* accurate. They're trying to be more 'precise', but the value they have will depend strongly on how exactly the value was calculated, and there are entirely reasonable design decisions that can cause them to differ between implementations.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b@gmail.com                                  ballbery@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
Date: Fri, 13 Oct 2017 19:59:32 +1100
To: "Brandon Allbery" <allbery.b [...] gmail.com>
CC: Carl Mäsak via RT <perl6-bugs-followup [...] perl.org>
From: <sisyphus1 [...] optusnet.com.au>
Subject: Re: [perl #132268] Floating point anomalies
Download (untitled) / with headers
text/plain 1.8k
From: Brandon Allbery Sent: Friday, October 13, 2017 4:15 AM To: sisyphus1@optusnet.com.au Cc: Carl Mäsak via RT Subject: Re: [perl #132268] Floating point anomalies On Thu, Oct 12, 2017 at 5:31 AM, <sisyphus1@optusnet.com.au> wrote: Perl6's printf() function looks a little suspect - though I might be missing something here. Show quoted text
>> As with perl5's say function, doubles are rounded to 14 decimal digits of >> precision
To correct that assertion, they both of course round to 15 decimal digits of precision. Show quoted text
> I question your use of 'accurate'. The low bits are *never* accurate. > They're trying to be more 'precise', but the value they have will depend > strongly on how exactly the value was calculated, and there are entirely > reasonable design decisions that can cause them to differ between > implementations.
I don't think there's anything "reasonable" about a printf() implementation that tells me: $ perl6 -e 'printf "%.16e\n", Num(sqrt(3e0));' 1.7320508075688800e+00 Perl6 knows quite well that a double assigned a value of 1.7320508075688800e+00 is not equivalent to the double returned by Num(sqrt(3e0)) : $ perl6 -e 'say "not equivalent" if 1.7320508075688800e0 != Num(sqrt(3e0));' not equivalent Furthermore, perl6 also knows quite well that a double assigned the value 1.7320508075688772e+00 *is* equivalent to the double returned by Num(sqrt(3e0)): $ perl6 -e 'say "ok" if 1.7320508075688772e0 == Num(sqrt(3e0));' ok It's bad enough that perl5 and perl6 round to 15 decimal digits of precision, but at least perl5's printf will give me 17 decimal digits when I ask it to (and I think perl6 should do the same): $ perl -e 'printf "%.16e\n", sqrt(3.0);' 1.7320508075688772e+00 As a feature request, it would also be nice to see "%a" formatting implemented as that then provides one with the means to see the exact value of the given double. Cheers, Rob
Date: Fri, 13 Oct 2017 08:15:33 -0400
To: sisyphus1 [...] optusnet.com.au
CC: Carl Mäsak via RT <perl6-bugs-followup [...] perl.org>
From: Brandon Allbery <allbery.b [...] gmail.com>
Subject: Re: [perl #132268] Floating point anomalies
Download (untitled) / with headers
text/plain 861b
On Fri, Oct 13, 2017 at 4:59 AM, <sisyphus1@optusnet.com.au> wrote:
Show quoted text
It's bad enough that perl5 and perl6 round to 15 decimal digits of precision, but at least perl5's printf will give me 17 decimal digits when I ask it to (and I think perl6 should do the same):

I am wondering if youve talked to any Intel FP engineers. 17 decimal digits sounds like you expect full internal 80-bit precision even if it's not in an internal register. Good luck.
(gcc does have ways of doing this on sufficiently recent processors. msvc does NOT. So, you've just demanded a Windows vs. Unix difference be enshrined in the language?)

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b@gmail.com                                  ballbery@sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 964b
On Fri, 13 Oct 2017 05:15:58 -0700, allbery.b@gmail.com wrote: Show quoted text
> On Fri, Oct 13, 2017 at 4:59 AM, <sisyphus1@optusnet.com.au> wrote: >
> > It's bad enough that perl5 and perl6 round to 15 decimal digits of > > precision, but at least perl5's printf will give me 17 decimal digits when > > I ask it to (and I think perl6 should do the same): > >
> > I am wondering if youve talked to any Intel FP engineers. 17 decimal digits > sounds like you expect full internal 80-bit precision even if it's not in > an internal register. Good luck. > (gcc does have ways of doing this on sufficiently recent processors. msvc > does NOT. So, you've just demanded a Windows vs. Unix difference be > enshrined in the language?) >
Perhaps the discussions about who talked to Intel engineers could be moved somewhere off the RT? The person fixing this ticket can figure out how much precision we can possibly give, without any luck wished upon those who made a feature request.
Subject: Floating-point literal in sink context changes the result of further expressions
From: Victor ADAM <victor.adam [...] derpymail.org>
Date: Fri, 20 Oct 2017 16:15:16 +0200
To: rakudobug [...] perl.org
Download (untitled) / with headers
text/plain 863b
How to reproduce ---------------- perl6 -e '$_ = 1e-1 + 2e-1; 3e-1; say $_ == 3e-1' perl6 -e '$_ = 1e-1 + 2e-1; .3e0; say $_ == 3e-1' Expected behavior ----------------- Both scripts should give the same result. If I understand floating-point handling correctly, they should both print `False`; but both printing `True` would also seem valid. Both scripts should warn about the use of a floating-point literal in sink context. Actual behavior --------------- The first script prints `True`. The second script prints `False`. Both scripts correctly warn: `Useless use of constant floating-point number 0.3 in sink context (line 1)`. Version information ------------------- This is Rakudo version 2017.09 built on MoarVM version 2017.09.1 implementing Perl 6.c. This was discussed (shortly) on IRC: https://irclog.perlgeek.de/perl6/2017-10-19#i_15324682
Subject: Sets can be equal even though their elements aren’t
From: Victor ADAM <victor.adam [...] derpymail.org>
Date: Fri, 20 Oct 2017 17:01:16 +0200
To: rakudobug <rakudobug [...] perl.org>
Download (untitled) / with headers
text/plain 773b
How to reproduce ---------------- perl6 -e 'my ($a, $b) = set(1e0), set(1e0 + 4e-15); say $a ~~ $b, $a.keys »≅« $b.keys' Expected behavior ----------------- Prints `False(False)`. Actual behavior --------------- Prints `True(False)`. This contradicts the documentation of the Setty ACCEPTS method: “Returns True if $other and self contain all the same elements, and no others.” The sets’ elements aren’t equal, or even approximately equal (≅), and yet ACCEPTS (~~) returns `True`. Note that other set methods show similar behavior: `1e0 ⊖ (1e0 + 4e-15)` is the empty set, `set(1e0, 1e0 + 4e-15)` only has one element… Version information ------------------- This is Rakudo version 2017.09 built on MoarVM version 2017.09.1 implementing Perl 6.c.
Subject: [MATH] Sets can be equal even though their elements aren’t
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 1.5k
On Fri, 20 Oct 2017 08:02:12 -0700, victor.adam@derpymail.org wrote: Show quoted text
> How to reproduce > ---------------- > > perl6 -e 'my ($a, $b) = set(1e0), set(1e0 + 4e-15); say $a ~~ $b, > $a.keys »≅« $b.keys' > > Expected behavior > ----------------- > > Prints `False(False)`. > > Actual behavior > --------------- > > Prints `True(False)`. > > This contradicts the documentation of the Setty ACCEPTS method: > “Returns True if $other and self contain all the same elements, and no > others.” The sets’ elements aren’t equal, or even approximately equal > (≅), and yet ACCEPTS (~~) returns `True`. > > Note that other set methods show similar behavior: `1e0 ⊖ (1e0 + > 4e-15)` is the empty set, `set(1e0, 1e0 + 4e-15)` only has one > element… > > Version information > ------------------- > > This is Rakudo version 2017.09 built on MoarVM version 2017.09.1 > implementing Perl 6.c.
By accident, I merged incorrect ticket… If you're fixing original issue, ignore the stuff about set()s… For set() issue, it isn't to do with set()s but with .Str and .WHICH on a Num losing a digit of precision. I see a couple of tickets[^1] for that issue already and I recall dogbertt++ was trying to fix it awhile back. <Zoffix__> m: dd (1e0).Str, (1e0 + 4e-15).Str <camelia> rakudo-moar 765dd6944: OUTPUT: «"1"␤"1"␤» <Zoffix__> m: dd (1e0).WHICH, (1e0 + 4e-15).WHICH <camelia> rakudo-moar 765dd6944: OUTPUT: «ObjAt.new("Num|1")␤ObjAt.new("Num|1")␤» [1] https://rt.perl.org/Ticket/Display.html?id=127201 [2] https://rt.perl.org/Ticket/Display.html?id=127184
RT-Send-CC: perl6-compiler [...] perl.org
On Fri, 20 Oct 2017 07:15:41 -0700, victor.adam@derpymail.org wrote: Show quoted text
> How to reproduce > ---------------- > > perl6 -e '$_ = 1e-1 + 2e-1; 3e-1; say $_ == 3e-1' > > perl6 -e '$_ = 1e-1 + 2e-1; .3e0; say $_ == 3e-1' > > Expected behavior > ----------------- > > Both scripts should give the same result. If I understand floating-point > handling correctly, they should both print `False`; but both printing `True` > would also seem valid. > > Both scripts should warn about the use of a floating-point literal in sink > context. > > Actual behavior > --------------- > > The first script prints `True`. The second script prints `False`. > > Both scripts correctly warn: `Useless use of constant floating-point number > 0.3 in sink context (line 1)`. > > Version information > ------------------- > > This is Rakudo version 2017.09 built on MoarVM version 2017.09.1 > implementing Perl 6.c. > > This was discussed (shortly) on IRC: > https://irclog.perlgeek.de/perl6/2017-10-19#i_15324682
This is the same cause as RT#132268. Merging there.
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 2.3k
On Wed, 11 Oct 2017 04:25:32 -0700, sisyphus wrote: Show quoted text
> Hi, > Some anomalous rounding behaviour on Ubuntu-16.04 was noted at > http://www.perlmonks.org/?node_id=1200326 > > Here are the specifics: > > $ perl6 --version > This is Rakudo version 2017.07 built on MoarVM version 2017.07 > implementing Perl 6.c. > > ======= > Issue 1 > ======= > > $ perl6 -e 'say Int(2e25);' > 20000000000000001811939328 > $ perl6 -e 'say Int(20e24);' > 19999999999999997516972032 > > That seems odd because 2e25 and 20e24 are exactly equivalent. > > ======= > Issue 2 > ======= > > $ perl6 -e 'say "WTF" if 1.000000000000001e0 == 1e0;' > WTF > > That seems odd because 1.000000000000001e0 and 1e0 are quite different > double precision values. According to perl5: > > $ perl -le 'print scalar reverse unpack "h*", pack "d<", > 1.000000000000001e0;' > 3ff0000000000005 > $ perl -le 'print scalar reverse unpack "h*", pack "d<", 1e0;' > 3ff0000000000000 > > Is it the intention of the perl6 developers that such discrepancies will be > addressed ? > > Cheers, > Rob
Thank you for the report. All the issues mentioned in the ticket are now fixed. - The mentioned printf issues look to have been resolved as well, even though no work to printf itself was done. - Somehow fixing Num stringification alone fixed the `1.000000000000001e0 == 1e0` bug. That was surprising and I filed https://github.com/rakudo/rakudo/issues/1647 to investigate that further - Support for '%a' in sprintf was mentioned in the ticket, but I suggest if there's real interest for that format, a separate ticket to be opened - There a Num-involved precision issue with drift in Str->Num->Str chains, filed as https://github.com/rakudo/rakudo/issues/1651 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/01d02dafb6 https://github.com/perl6/roast/commit/b6d5364fe0 https://github.com/perl6/roast/commit/855af84f82 https://github.com/perl6/roast/commit/f4a6c635f4 https://github.com/perl6/roast/commit/d1faf1d049


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