Re: Small Perl 6 discoveries III, Ints
by syphilis (Archbishop) on Sep 28, 2017 at 23:46 UTC
|
Anybody want to try and explain this one?
I find this is a bit interesting.
I can reproduce it on perl-5.26.0 (nvtype=double):
C:\>perl -le "printf '%.0f', 2e25;"
20000000000000001811939328
C:\>perl -le "printf '%.0f', 20e24;"
19999999999999997516972032
It happens because 20e24 is miscalculated (off by one ULP).
It's an error that doesn't occur on all of my "double" perls. For example, my perl-5.16.0 is not subject to this issue.
UPDATE: Actually, it occurs on all of my "double" builds of perl that were built using an x86_64 compiler.
I also see the same bug on perl-5.26.0 on Linux (Ubuntu):
$ perl -le 'printf "%.0f\n", 2e25;'
20000000000000001811939328
$ perl -le "printf '%.0f', 20e24;"
19999999999999997516972032
Odd that perl6 should have managed to inherit the same failing.
Are you using a current version of perl6 ?
Cheers, Rob
| [reply] [d/l] [select] |
|
|
Rakudo star 2017.07. It's the third and fourth lines that have me scratching my head, though.
| [reply] |
Re: Small Perl 6 discoveries III, Ints
by holli (Abbot) on Sep 29, 2017 at 05:50 UTC
|
The exponential notation always produces a Num (and therefore introduces rounding errors), even when a value could be expressed as a Rat. This is by design as I have been told. It works correctly though if you do this:
> 2*(10**25)
20000000000000000000000000
> 20*(10**24)
20000000000000000000000000
> 2*(10**25) == 20*(10**24)
True
holli
You can lead your users to water, but alas, you cannot drown them.
| [reply] [d/l] [select] |
|
|
Yes, thanks. We've discovered that the Int is actually working correctly in this case, but the Num is broken.
| [reply] |
|
|
| [reply] [d/l] |
|
|
Re: Small Perl 6 discoveries III, Ints
by virtualsue (Vicar) on Sep 29, 2017 at 14:57 UTC
|
The code for Perl 6 Rakudo is on github and there is an up-to-date document on how to report bugs in it on the github project wiki just in case anyone feels like getting more involved.
Rakudo codebase
Rakudo bug tracking
| [reply] |
|
|
... there is an up-to-date document on how to report bugs in it on the github project wiki just in case anyone feels like getting more involved
Not that I really wanted to get involved, but I was a little curious about the status of some of the issues raised in this thread.
So, last night, I submitted a bug report that referred to 2 of the issues raised here:
1) that perl6 evaluates '1.000000000000001e0 == 1e0' as true;
2) that perl6 produces different outputs for 'Int(2e25)' and 'Int(20e24)'.
Turns out that the second is the result of a known issue with perl6's way of constructing Nums ... not so sure that the first one is exactly the same issue.
Anyway, Zoffix Znet's reply to the bug report informs us that these bugs will be fixed, though it's presently not all that high on the list of priorities.
Seems that perl6 assigns 2e25 as 2 * 1e25, but assigns 20e24 as 20 * 1e24. Hence the discrepancy.
Cheers, Rob
| [reply] [d/l] [select] |
|
|
The problem can be summarized as follows:
- Some platforms ship with a vendor-supplied libc that's really sloppy.
- Because of this, perl5 development has been slowly replacing use of libc with home-grown code.
- However, GNU libc is really good. It's the default libc on many platforms, and it's available on most.
- As a result, many perl programmers have been experiencing slowly deteriorating quality of numeric implementation for around two decades. Perl6 accelerates this trend.
| [reply] |
|
|
|
|
Be my guest. IDGAF, and the perl6 developers obviously don't either. My entire qualification with Perl6 is that I've read the first three chapters of Perl 6 Deep Dive and kicked it around a little bit in my spare time. Everywhere I look, I see bugs.
| [reply] |
|
|
Oh, that's so cute. AM even provided a link to an explanation for 'IDGAF'.
I had already assumed that the anonymous coward who started this thread wouldn't be interested in what I wrote. I was talking to other people who might happen to see the thread.
| [reply] |
|
|
|
|
Re: Small Perl 6 discoveries III, Ints
by Anonymous Monk on Sep 29, 2017 at 01:41 UTC
|
Well, mystery sort of solved. It seems to be some kind of misguided parser optimization. It will reuse a floating-point literal for another value that's approximately equal.
> my $a = 2e25; my $b = 20e24; $a - $b
0
> (Int($a), $a.WHERE)
(20000000000000001811939328 4431024856)
> (Int($b), $b.WHERE)
(20000000000000001811939328 4431024856)
> my $c = Num('2e25'); my $d = Num('20e24'); $c - $d
4294967296
> (Int($c), $c.WHERE)
(20000000000000001811939328 4431025568)
> (Int($d), $d.WHERE)
(19999999999999997516972032 4431025664)
Observe that $a and $b refer to the same object (they have the same address), while $c and $d are distinct. | [reply] [d/l] |
|
|
It will reuse a floating-point literal for another value that's approximately equal
I'll speculate that it will only engage in "reuse" when the two values are exactly equal. (Bear in mind that 2e25 and 20e24 are exactly equal.)
So it should be a valid optimization - it's only being brought undone by the miscalculation of 20e24.
The miscalculation of 20e24 is a bug in perl6 that should be reported, though FAIK it might already have been fixed.
UPDATE: The same miscalculation is also a bug in perl5 - but such miscalculations are already known in perl 5
Cheers, Rob
| [reply] |
|
|
> 1.000000000000001e0 - 1e0
0
> 1.000000000000001e0 - 1
1.11022302462516e-15
| [reply] [d/l] |
|
|
|
|
|
|
|
|