Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

== on Num literals produces bogus answer #5521

Closed
p6rt opened this issue Aug 2, 2016 · 7 comments
Closed

== on Num literals produces bogus answer #5521

p6rt opened this issue Aug 2, 2016 · 7 comments
Labels

Comments

@p6rt
Copy link

p6rt commented Aug 2, 2016

Migrated from rt.perl.org#128820 (status was 'resolved')

Searchable as RT128820$

@p6rt
Copy link
Author

p6rt commented Aug 2, 2016

From zefram@fysh.org

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

@p6rt
Copy link
Author

p6rt commented Aug 2, 2016

From @pmichaud

On Tue, Aug 02, 2016 at 10​:55​:34AM -0700, Zefram wrote​:

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​:

my $a = 1180591620717411303424e0
1.18059162071741e+21
my $b = 1180591620717411333333e0
1.18059162071741e+21
$a.Int
1180591620717411303424
$b.Int
1180591620717411303424
$a == $b
True
$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

@p6rt
Copy link
Author

p6rt commented Aug 2, 2016

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Aug 2, 2016

From zefram@fysh.org

Patrick R. Michaud via RT wrote​:

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.

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​:

(1180591620717411303424e0, 1180591620717409992704e0).map(*.Int)
(1180591620717411303424 1180591620717411303424)
(1180591620717409992704e0, 1180591620717411303424e0).map(*.Int)
(1180591620717409992704 1180591620717409992704)
("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

@p6rt
Copy link
Author

p6rt commented Aug 19, 2016

From zefram@fysh.org

Additional​: this also happens with Complex literals, where the real or
imaginary parts suffer this as Nums.

-zefram

@p6rt
Copy link
Author

p6rt commented Apr 13, 2018

From @zoffixznet

On Tue, 02 Aug 2016 10​:55​:34 -0700, zefram@​fysh.org wrote​:

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​: MoarVM/MoarVM@067c0594103a025
  MoarVM/MoarVM@8841c4241b4faa8
  MoarVM/MoarVM@af2eb8a7f7d4344
  MoarVM/MoarVM@4d3fc2818d0032b
  rakudo/rakudo@8422d7b4e23678b
  rakudo/rakudo@a2a2a745c4242d1
Test​: Raku/roast@52c60ce5c283dd5b8
  Raku/roast@bba5e9fdda431c9f4

@p6rt
Copy link
Author

p6rt commented Apr 13, 2018

@zoffixznet - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Apr 13, 2018
@p6rt p6rt added the Bug label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant