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

Inconsistent string-to-number conversion for various zero strings #10828

Open
p5pRT opened this issue Nov 14, 2010 · 1 comment
Open

Inconsistent string-to-number conversion for various zero strings #10828

p5pRT opened this issue Nov 14, 2010 · 1 comment

Comments

@p5pRT
Copy link

p5pRT commented Nov 14, 2010

Migrated from rt.perl.org#79212 (status was 'new')

Searchable as RT79212$

@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2010

From @cpansprout

See the table toward the end of the forwarded message. The -$nz coercion problem that brought this up has already been fixed.

Begin forwarded message​:

From​: Zefram <zefram@​fysh.org>
Date​: October 24, 2010 3​:10​:53 PM PDT
To​: Father Chrysostomos <sprout@​cpan.org>
Subject​: Re​: Recent Data​::Float changes

Father Chrysostomos wrote​:

In several places, you now copy scalars before passing them to the
negation operator. Which change made this necessary?

I didn't determine which change it was. There were multiple effects in
play, and my concern was to get the code working rather than to establish
underlying theory for Perl's arithmetic. (I gave up a long time ago on
it making sense.)

One of the main changes I made, involving extra copying, was to the
code that I use to determine the flavour of a zero. The old and new
versions are​:

sub zpat0($) { my($z) = @​_; sprintf("%+.f%+.f%+.f", $z, -$z, - -$z) }
sub zpat1($) { my($z) = @​_; my $nz = -$z; sprintf("%+.f%+.f%+.f",$z,$nz,-$nz) }

Naively they look equivalent, and up to 5.13.5 they are equivalent.
They give answers "+0+0+0" for integer (unsigned zero), "+0-0+0" for
positive zero, and "-0+0-0" for negative zero. The reason for the
apparently-redundant double negation part is because I've previously
seen some arithmetic operations mangle a zero into a hybrid state,
where it appears to be negative but its negation is an unsigned zero.
This yields "-0+0+0". There's an equivalent state for the positive zero,
but since it yields "+0+0+0" it's indistinguishable from an unsigned
zero by this mechanism.

On 5.13.6 the old version doesn't give consistent results any more,
even for untainted zeroes. The more conservative new version still
plays nicely​:

$ perl5.13.5 -Mzpat -lwe 'print zpat0(-0.0), " ", zpat1(-0.0)'
-0+0-0 -0+0-0
$ perl5.13.6 -Mzpat -lwe 'print zpat0(-0.0), " ", zpat1(-0.0)'
-0+0+0 -0+0-0

It appears that negation is now side-effecting the zeroes into the
inconsistent hybrid state, which it wasn't doing before​:

$ perl5.13.5 -lwe '$z=-0.0; printf "%+.f %+.f\n", $z, - -$z'
-0 -0
$ perl5.13.5 -lwe '$z=-0.0; -$z; printf "%+.f %+.f\n", $z, - -$z'
Useless use of negation (-) in void context at -e line 1.
-0 -0
$ perl5.13.6 -lwe '$z=-0.0; printf "%+.f %+.f\n", $z, - -$z'
-0 -0
$ perl5.13.6 -lwe '$z=-0.0; -$z; printf "%+.f %+.f\n", $z, - -$z'
Useless use of negation (-) in void context at -e line 1.
-0 +0

So the old version of zpat now taints $z enough internally to skew
the result. The new version taints both $z and $nz, but throws them
away before the taint can damage the output.

Other changes that I've made in Data​::Float and Scalar​::Number relate to
which kind of zero is yielded from each possible zero-valued expression.
I've particularly made Scalar​::Number's test suite more conservative
about this; it's doing more autodetection, where it used to assume some
of the answers. Here's a comparison of the most common cases​:

expression   zpat/5\.13\.5   zpat/5\.13\.6
0            \+0\+0\+0        \+0\+0\+0
\+0           \+0\+0\+0        \+0\+0\+0
\-0           \+0\+0\+0        \+0\+0\+0
0\.0          \+0\-0\+0        \+0\-0\+0
\+0\.0         \+0\-0\+0        \+0\-0\+0
\-0\.0         \-0\+0\-0        \-0\+0\-0
"0"          \+0\+0\+0        \+0\-0\+0
"\+0"         \+0\-0\+0        \+0\-0\+0
"\-0"         \-0\+0\-0        \+0\-0\+0
"0\.0"        \+0\+0\+0        \+0\-0\+0
"\+0\.0"       \+0\-0\+0        \+0\-0\+0
"\-0\.0"       \-0\+0\-0        \-0\+0\-0

Numeric literal zeroes are signed or not according to whether they
contain a radix point, and that hasn't changed. Strings that look like
numberic zeroes used to be signed iff they started with a sign character.
Now they are always signed, but the numeric sign is only negative if
the string starts with a minus character *and* contains a dot.

I don't hugely care which flavour of zero a zeroish string produces.
But if you want suggestions, I'd prefer that they numerify to the same
thing as the numeric literal expression involving the same characters.
E.g., "-0" should numerically act as an unsigned zero, like -0, rather
than being either a negative zero (as in 5.13.5) or a positive zero
(as in 5.13.6).


Flags​:
  category=core
  severity=low


Site configuration information for perl 5.13.6​:

Configured by sprout at Thu Nov 11 04​:29​:30 PST 2010.

Summary of my perl5 (revision 5 version 13 subversion 6) configuration​:
  Commit id​: fc6b470
  Platform​:
  osname=darwin, osvers=10.4.0, archname=darwin-2level
  uname='darwin pint.local 10.4.0 darwin kernel version 10.4.0​: fri apr 23 18​:28​:53 pdt 2010; root​:xnu-1504.7.4~1release_i386 i386 '
  config_args='-de -Dusedevel -Doptimize=-Os -Dusemymalloc=y -Duseshrplib=true -Duselargefiles=yes -Duseposix=true -Dhint-recommended =Duseperlio=yes -Duse64bitint=yes'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=undef, use64bitall=undef, uselongdouble=undef
  usemymalloc=y, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
  optimize='-Os',
  cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.2.1 (Apple Inc. build 5664)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib
  libs=-ldbm -ldl -lm -lutil -lc
  perllibs=-ldl -lm -lutil -lc
  libc=/usr/lib/libc.dylib, so=dylib, useshrplib=true, libperl=libperl.dylib
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches​:
 


@​INC for perl 5.13.6​:
  /usr/local/lib/perl5/site_perl/5.13.6/darwin-2level
  /usr/local/lib/perl5/site_perl/5.13.6
  /usr/local/lib/perl5/5.13.6/darwin-2level
  /usr/local/lib/perl5/5.13.6
  /usr/local/lib/perl5/site_perl
  .


Environment for perl 5.13.6​:
  DYLD_LIBRARY_PATH (unset)
  HOME=/Users/sprout
  LANG=en_US.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/bin​:/bin​:/usr/sbin​:/sbin​:/usr/local/bin​:/usr/X11/bin​:/usr/local/bin
  PERL_BADLANG (unset)
  SHELL=/bin/bash

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

No branches or pull requests

2 participants