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

$] sometimes has bad numeric value #10095

Closed
p5pRT opened this issue Jan 19, 2010 · 8 comments
Closed

$] sometimes has bad numeric value #10095

p5pRT opened this issue Jan 19, 2010 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 19, 2010

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

Searchable as RT72210$

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2010

From zefram@fysh.org

On some perl versions, the numeric value of $] is not equal to the
value that results from a string-to-NV conversion from the conventional
decimal-fraction form of the perl version number. This makes certain
kinds of version check fail​:

$ perlver 5.8.8-i32-f63 perl -le 'print $], " ", $] <= 5.008008 ? "le" : "gt"'
5.008008 gt

That's perl 5.8.8 *configured to use x86 long double*. The same version
using ordinary double works fine​:

$ perlver 5.8.8-i32-f52 perl -le 'print $], " ", $] <= 5.008008 ? "le" : "gt"'
5.008008 le

It turns out that on the long-double 5.8.8 $]'s numeric value is the next
NV value available above the usual conversion of 5.008008. The double
5.8.8 has them equal, as expected​:

$ perlver 5.8.8-i32-f63 perl -MData​::Float=float_hex -le 'print float_hex($]); print float_hex(5.008008)'
+0x1.408333fc86cebbbcp+2
+0x1.408333fc86cebbbap+2
$ perlver 5.8.8-i32-f52 perl -MData​::Float=float_hex -le 'print float_hex($]); print float_hex(5.008008)'
+0x1.408333fc86cecp+2
+0x1.408333fc86cecp+2

On a systematic check of every version from 5.6.0 to date, except for
the 5.7s (which I don't have installed), I found these anomalies​:

5.6.1 long-double $] &gt; "$]"
5.6.2 double $] &gt; "$]"
5.8.1 long-double $] &gt; "$]"
5.8.4 long-double $] &gt; "$]"
5.8.7 long-double $] &gt; "$]"
5.8.8 long-double $] &gt; "$]"
5.9.1 double $] &gt; "$]"
5.9.1 long-double $] &gt; "$]"

In no case was $] *less* than the numeric value of "$]". So version
checks of the form "$] >= 5.whatever" or "$] < 5.whatever" apparently
always work, though I don't have any theoretical explanation for why
that should always be the case.

Possible cause of failure​:

$ perlver 5.10.1-i32-f52 perl -MData​::Float=float_hex -lwe 'print float_hex(5.009001); print float_hex(5+0.009+0.000001)'
+0x1.409378ee28672p+2
+0x1.409378ee28673p+2
$ perlver 5.10.1-i32-f63 perl -MData​::Float=float_hex -lwe 'print float_hex(5.009001); print float_hex(5+0.009+0.000001)'
+0x1.409378ee28672756p+2
+0x1.409378ee28672758p+2

If $] is indeed being built up by summing the parts in this way, suffering
multiple rounding, we would expect (for example) 5.11.3 to suffer the
same anomaly on IEEE double systems. Since it in fact doesn't, I suspect
that this problem does not occur with the new version-handling code.
I'd like to see this confirmed by someone who knows the version code,
though, which is why I'm opening this ticket. We should also check the
interaction of version numbers with bug #41202.

(I knew we were skating on thin ice in using binary floating point to
represent decimal-fraction version numbers. But I didn't anticipate this
failure mode. I expected a couple of forms of truncation to bite us,
not arithmetic rounding error.)

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2010

From @xdg

On Tue, Jan 19, 2010 at 4​:07 PM, Zefram <perlbug-followup@​perl.org> wrote​:

On some perl versions, the numeric value of $] is not equal to the
value that results from a string-to-NV conversion from the conventional
decimal-fraction form of the perl version number.  This makes certain
kinds of version check fail​:

$ perlver 5.8.8-i32-f63 perl -le 'print $], " ", $] <= 5.008008 ? "le" : "gt"'
5.008008 gt

perlvar does warn about this​:

  The floating point representation can sometimes lead to
  inaccurate numeric comparisons. See $^V for a more modern
  representation of the Perl version that allows accurate string
  comparisons.

It's always better to think of "version numbers" as "version strings". E.g.

  $ perl588 -le 'print $], " ", $] <= 5.008008 ? "le" : "gt"'
  5.008008 gt

  $ perl588 -le 'print $], " ", $] le 5.008008 ? "le" : "gt"'
  5.008008 le

-- David

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2010

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

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2010

From @xdg

On Tue, Jan 19, 2010 at 4​:07 PM, Zefram <perlbug-followup@​perl.org> wrote​:

If $] is indeed being built up by summing the parts in this way, suffering
multiple rounding, we would expect (for example) 5.11.3 to suffer the
same anomaly on IEEE double systems.  Since it in fact doesn't, I suspect
that this problem does not occur with the new version-handling code.
I'd like to see this confirmed by someone who knows the version code,
though, which is why I'm opening this ticket.  We should also check the
interaction of version numbers with bug #41202.

For the record, it appears to be constructed equivalent to this
(except using the underlying API)​:

  $] = version-&gt;new($^V)->numify;

numify() builds it up in parts *as a string* from the components of
$^V. Thus, it starts out as a string and gets converted to a number
on numeric comparison. From what I can tell, both literals and
converted strings that look like floats all goes through Atof()
eventually so it should be consistent.

I think we can close this ticket.

-- David

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2010

From @nwc10

On Tue, Jan 19, 2010 at 01​:07​:35PM -0800, Zefram wrote​:

On a systematic check of every version from 5.6.0 to date, except for
the 5.7s (which I don't have installed), I found these anomalies​:

5.6.1 long-double $] &gt; "$]"
5.6.2 double $] &gt; "$]"
5.8.1 long-double $] &gt; "$]"
5.8.4 long-double $] &gt; "$]"
5.8.7 long-double $] &gt; "$]"
5.8.8 long-double $] &gt; "$]"
5.9.1 double $] &gt; "$]"
5.9.1 long-double $] &gt; "$]"

I wondered if it might be the implementation of atof, but that was only added
after 5.6.1 shipped​:

http​://perl5.git.perl.org/perl.git/commit/1f727ac0e62bc2e4

If $] is indeed being built up by summing the parts in this way, suffering
multiple rounding, we would expect (for example) 5.11.3 to suffer the
same anomaly on IEEE double systems. Since it in fact doesn't, I suspect

Assuming that you did your tests on x86, I thought that x86 (well, x87)
had this "fun" feature whereby it often does maths at the precision of the
FPU (ie long double) and only truncates to double (or float) when (and *if*)
it needs to write to memory. Hence it's quite capable of producing
fractionally different results for a calculation depending on register spill.
Could this explain it?

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2010

From zefram@fysh.org

Nicholas Clark wrote​:

Assuming that you did your tests on x86, I thought that x86 (well, x87)
had this "fun" feature whereby it often does maths at the precision of the
FPU (ie long double) and only truncates to double (or float) when (and *if*)
it needs to write to memory.

That's under compiler control, and a sane compiler will ensure consistent
semantics. C89 and all later standards require consistent semantics.
gcc has an option to enable fast-but-inconsistent arithmetic.

Could this explain it?

If inconsistent arithmetic were enabled, it could lead to getting
different answers from the addition in different circumstances. The use
of inconsistent rounding modes (governed less by the C standards) could
also do this. But neither of these is an issue on the pretty sane
combination of gcc on x87.

-zefram

@p5pRT
Copy link
Author

p5pRT commented May 18, 2012

From @cpansprout

On Tue Jan 19 19​:49​:09 2010, xdaveg@​gmail.com wrote​:

On Tue, Jan 19, 2010 at 4​:07 PM, Zefram <perlbug-followup@​perl.org> wrote​:

If $] is indeed being built up by summing the parts in this way,
suffering
multiple rounding, we would expect (for example) 5.11.3 to suffer the
same anomaly on IEEE double systems. �Since it in fact doesn't, I
suspect
that this problem does not occur with the new version-handling code.
I'd like to see this confirmed by someone who knows the version code,
though, which is why I'm opening this ticket. �We should also check the
interaction of version numbers with bug #41202.

For the record, it appears to be constructed equivalent to this
(except using the underlying API)​:

$] = version-&gt;new($^V)->numify;

numify() builds it up in parts *as a string* from the components of
$^V. Thus, it starts out as a string and gets converted to a number
on numeric comparison. From what I can tell, both literals and
converted strings that look like floats all goes through Atof()
eventually so it should be consistent.

I think we can close this ticket.

And I missed this particular message when I was going through tickets a
while ago.

Zefram confirms that it is now fixed​:
nntp​://nntp.perl.org/20120518130430.GQ11209@​lake.fysh.org

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented May 18, 2012

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant