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

-0.0 has variable Boolean value #9013

Closed
p5pRT opened this issue Sep 3, 2007 · 14 comments
Closed

-0.0 has variable Boolean value #9013

p5pRT opened this issue Sep 3, 2007 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 3, 2007

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

Searchable as RT45133$

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

From zefram@fysh.org

Created by zefram@fysh.org

A negative floating point zero is distinct from a positive zero, and
stringifies as "-0". In a Boolean context it behaves inconsistently.
A pristine negative zero acts as Boolean false, presumably based on its
numeric value of zero​:

$ perl -le '$a=-0.0; print $a?"true"​:"false"'
false

But if it is stringified at some point, then it acts as Boolean true,
presumably based on its string value​:

$ perl -le '$a=-0.0; "$a"; print $a?"true"​:"false"'
true

I'm not sure whether negative zero should be true or false, but I think
it should be consistent about it.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl v5.8.8:

Configured by Debian Project at Wed Dec  6 23:17:41 UTC 2006.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=linux, osvers=2.6.18.3, archname=i486-linux-gnu-thread-multi
    uname='linux saens 2.6.18.3 #1 smp sat nov 25 13:39:52 est 2006 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.8 -Dsitearch=/usr/local/lib/perl/5.8.8 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.8 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.1.2 20061115 (prerelease) (Debian 4.1.1-20)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.3.6.so, so=so, useshrplib=true, libperl=libperl.so.5.8.8
    gnulibc_version='2.3.6'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.8:
    /etc/perl
    /usr/local/lib/perl/5.8.8
    /usr/local/share/perl/5.8.8
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.8
    /usr/share/perl/5.8
    /usr/local/lib/site_perl
    /usr/local/lib/perl/5.8.4
    /usr/local/share/perl/5.8.4
    .


Environment for perl v5.8.8:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_GB
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/pub/i686-pc-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

From @davidnicol

On 9/2/07, via RT Zefram <perlbug-followup@​perl.org> wrote​:

I'm not sure whether negative zero should be true or false, but I think
it should be consistent about it.

An argument could be made that in the larger picture of Boolean coercion
in perl, the current behavior -- negative zero as a number is false but as a
string it is true -- _is_ consistent. The apparently inconsistent coercion
of negative zero (itself a debatable construction) is the dark side of the
happy path where "0" is false and "0 Cleveland" is true.

This could be a useful, instructive corner case to help understand the
nuanced consistency. Document it? Encourage testing (0 + $val) instead
of ($val) whenever $val might be negative zero? What exactly can produce
negative zero, anyway, aside from $val = -0.0?

I think we're well within the "well don't do that then" category; on the
other hand this behjavior is definately a crack in the facade of total
transparent equivalence between numbers and strings which it would
make sense to seal.

I'm for "-0" becoming false, along with "0" and "". Then again that change
might break something somewhere. Another fix would be to stringify -0.0
to plain old 0, although that too might break something somewhere.

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

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

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

From shouldbedomo@mac.com

On 2007–09–03, at 21​:16, David Nicol wrote​:

What exactly can produce
negative zero, anyway, aside from $val = -0.0?

$ perl -lwe 'print -1/1e309'
-0

for IEEEish machines.

... corner case ...

In IEEE fp as well as in Perl. Basically, it means "too small for me
to be able to represent it, but would be less than zero if I could".
--
Dominic Dunlop

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

From @ysth

On Mon, September 3, 2007 12​:30 pm, Dominic Dunlop wrote​:

On 2007�09�03, at 21​:16, David Nicol wrote​:

What exactly can produce
negative zero, anyway, aside from $val = -0.0?

$ perl -lwe 'print -1/1e309'
-0

for IEEEish machines.

... corner case ...

In IEEE fp as well as in Perl. Basically, it means "too small for me
to be able to represent it, but would be less than zero if I could". --

Aka true. I thought (and I may misremember) the last go round on this
concluded that NV -0.0 should be true.

@p5pRT
Copy link
Author

p5pRT commented Sep 3, 2007

From nospam-abuse@bloodgate.com

On Monday 03 September 2007 21​:30​:10 Dominic Dunlop wrote​:

On 2007–09–03, at 21​:16, David Nicol wrote​:

What exactly can produce
negative zero, anyway, aside from $val = -0.0?

$ perl -lwe 'print -1/1e309'
-0

for IEEEish machines.

# perl -Mbignum -lwe 'print -1/1e309'

:)

Tels

--
Signed on Mon Sep 3 22​:52​:52 2007 with key 0x93B84C15.
View my photo gallery​: http​://bloodgate.com/photos
PGP key on http​://bloodgate.com/tels.asc or per email.

"...no one would risk manipulating votes in an election because it's
against the law and carries a heavy penalty..."

  -- Diebold spokesman David Bear

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2007

From zefram@fysh.org

I wrote​:

I'm not sure whether negative zero should be true or false, but I think
it should be consistent about it.

On reflection, I think negative zero should stringify as "0" and be
Boolean false. This is the least surprising behaviour for code that
works only with the numerical value and isn't necessarily expecting
floating point semantics for zero. It's also consistent with
floating point positive zero, which already stringifies to "0"​: the
number->string->number round trip currently converts positive zero to
unsigned (integer) zero, and should probably do the same to negative zero.

There was a discussion of negative zero for bug#39875 "-0.0 loses
signedness upon numeric comparison", which among its diverse subthreads
looked at stringification and (briefly) Boolean values of zeroes.
In there I suggested making all zeroes round-trip correctly from
number->string->number, but on reflection the variety of stringifications
for the same numeric value would be confusing.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Sep 12, 2007

From nospam-abuse@bloodgate.com

Moin,

On Tuesday 11 September 2007 23​:52​:18 Zefram wrote​:

I wrote​:

I'm not sure whether negative zero should be true or false, but I think
it should be consistent about it.

On reflection, I think negative zero should stringify as "0" and be
Boolean false. This is the least surprising behaviour for code that
works only with the numerical value and isn't necessarily expecting
floating point semantics for zero. It's also consistent with
floating point positive zero, which already stringifies to "0"​: the
number->string->number round trip currently converts positive zero to
unsigned (integer) zero, and should probably do the same to negative
zero.

I would welcome this change (That "+0" and "-0" become "0" on
stringification) because that would also make it consistent with BigInt et.
al.

All the best,

Tels

--
Signed on Wed Sep 12 18​:33​:28 2007 with key 0x93B84C15.
Get one of my photo posters​: http​://bloodgate.com/posters
PGP key on http​://bloodgate.com/tels.asc or per email.

"I never forget a face, but in your case I'll be glad to make an
exception."

  -- Groucho Marx

@p5pRT
Copy link
Author

p5pRT commented Sep 12, 2007

From @davidnicol

I would welcome this change (That "+0" and "-0" become "0" on
stringification) because that would also make it consistent with BigInt et.
al.

C<use feature IEEEfp;> anyone?

--
The Wisconsin Employees' right to know law regarding toxic substances
specifically exempts Lutefisk -- Wikipedia

@p5pRT
Copy link
Author

p5pRT commented Sep 12, 2007

From nospam-abuse@bloodgate.com

Moin,

On Wednesday 12 September 2007 20​:07​:57 David Nicol wrote​:

I would welcome this change (That "+0" and "-0" become "0" on
stringification) because that would also make it consistent with BigInt
et. al.

C<use feature IEEEfp;> anyone?

Just for the record​: I will not add support for "-0" into BigInt et al. - I
have better things to waste my time on. IMO it is not worth adding
complexity and slow-downs to the code just to care for some bizarre special
case.

All the best,

Tels

--
Signed on Wed Sep 12 20​:25​:27 2007 with key 0x93B84C15.
Get one of my photo posters​: http​://bloodgate.com/posters
PGP key on http​://bloodgate.com/tels.asc or per email.

"If you think the problem is bad now, just wait until we've solved it."

  -- Arthur Kasspe

@p5pRT
Copy link
Author

p5pRT commented Aug 8, 2010

From @cpansprout

I think stringifying -0.0 as 0 is the best solution to this. And it seems that Larry Wall was also planning to have perl do that, or was at least toying with the idea. Since version 5.00, there has been an #ifdef FIXNEGATIVEZERO that does it this way. This patch simple removes that #ifdef.

Here are some tests. I have no idea where to put them. t/op/numconvert.t sounds like the right place, but is not structured in a way that fits these tests​:

ok(-0.0 eq "0", 'negative zero stringifies as 0');
ok(!-0.0, "neg zero is boolean false");
my $nz = -0.0; "$nz"; ok(!$nz, 'previously stringified -0.0 is boolean false');

@p5pRT
Copy link
Author

p5pRT commented Aug 8, 2010

From @cpansprout

Inline Patch
diff -Nup blead/sv.c blead-45133--0/sv.c
--- blead/sv.c	2010-08-01 13:50:12.000000000 -0700
+++ blead-45133--0/sv.c	2010-08-07 17:50:48.000000000 -0700
@@ -2775,13 +2775,11 @@ Perl_sv_2pv_flags(pTHX_ register SV *con
 	    {
 		dVAR;
 
-#ifdef FIXNEGATIVEZERO
 		if (len == 2 && tbuf[0] == '-' && tbuf[1] == '0') {
 		    tbuf[0] = '0';
 		    tbuf[1] = 0;
 		    len = 1;
 		}
-#endif
 		SvUPGRADE(sv, SVt_PV);
 		if (lp)
 		    *lp = len;
@@ -2968,12 +2966,10 @@ Perl_sv_2pv_flags(pTHX_ register SV *con
 	    Gconvert(SvNVX(sv), NV_DIG, 0, s);
 	}
 	RESTORE_ERRNO;
-#ifdef FIXNEGATIVEZERO
         if (*s == '-' && s[1] == '0' && !s[2]) {
 	    s[0] = '0';
 	    s[1] = 0;
 	}
-#endif
 	while (*s) s++;
 #ifdef hcx
 	if (s[-1] == '.')

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

From @cpansprout

On Sun Aug 08 12​:15​:41 2010, sprout wrote​:

I think stringifying -0.0 as 0 is the best solution to this. And it
seems that Larry Wall was also planning to have perl do that, or
was at least toying with the idea. Since version 5.00, there has
been an #ifdef FIXNEGATIVEZERO that does it this way. This patch
simple removes that #ifdef.

Here are some tests. I have no idea where to put them.
t/op/numconvert.t sounds like the right place, but is not
structured in a way that fits these tests​:

ok(-0.0 eq "0", 'negative zero stringifies as 0');
ok(!-0.0, "neg zero is boolean false");
my $nz = -0.0; "$nz"; ok(!$nz, 'previously stringified -0.0 is boolean
false');

Applied, with Jesse’s approval, as afa7457.

@p5pRT
Copy link
Author

p5pRT commented Oct 4, 2010

@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
Projects
None yet
Development

No branches or pull requests

1 participant