Navigation Menu

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 generation of floating negative zero #11695

Closed
p5pRT opened this issue Oct 12, 2011 · 5 comments
Closed

Inconsistent generation of floating negative zero #11695

p5pRT opened this issue Oct 12, 2011 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 12, 2011

Migrated from rt.perl.org#101262 (status was 'rejected')

Searchable as RT101262$

@p5pRT
Copy link
Author

p5pRT commented Oct 12, 2011

From Keith.S.Thompson@gmail.com

Created by Keith.S.Thompson@gmail.com

This is based on a question posted to stackoverflow.com​:
http​://stackoverflow.com/questions/7746804/perl-sprintf-result/
(The poster identified him or herself only as "smith".)

This program​:
#!/usr/bin/perl

use strict;
use warnings;

my $x = -1.0 * 0.0;
my $y = -1.5 * 0.0;

printf "x = $x = %f\n", $x;
printf "y = $y = %f\n", $y;

produces this output​:
x = 0 = 0.000000
y = -0 = -0.000000

I get the same result with perl 5.10.1 (the default version on my
system) and the "blead" version built from source on 2011-09-13.
(I'm building a newer version now and will follow up if there's
any difference.)

It's reasonable for a negative number multiplied by zero to yield
a negative zero. It would also be reasonable for it to yield a
positive zero. What seems unreasonable is that -1.0*0.0 and -1.5*0.0
yield different results.

I had a couple of hypotheses about this. The first was that
the value being printed by the original program (which had a more
complex expression than the one above) might have been producing a
very small negative value that was being rounded to -0.0 by sprintf
with a "%0.1f" format, but changing the format shows that it's a
true negative zero. The second was that one value might be computed
at compile time and the other at execution time, using inconsistent
methods, but replacing all the constants with calls to a function
that shouldn't be optimizable yielded the same results.

Further experiment shows that multiplying a negative integral value by
0.0 yields -0.0, but multiplying a negative non-integral value by 0.0
yields 0.0.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.15.2:

Configured by kst at Mon Sep 12 18:26:31 PDT 2011.

Summary of my perl5 (revision 5 version 15 subversion 2) configuration:
  Commit id: 53b10071adc2e67f88bbc0d32e2dc6f982598c98
  Platform:
    osname=linux, osvers=2.6.38-11-generic, archname=i686-linux
    uname='linux kvetch 2.6.38-11-generic #48-ubuntu smp fri jul 29 19:05:14 utc 2011 i686 i686 i386 gnulinux '
    config_args='-de -Dprefix=/usr/local/apps/perl-blead-2011-09-13-012629Z -Dusedevel'
    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=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.5.2', 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 =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /usr/lib/i386-linux-gnu /lib64 /usr/lib64
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.13'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.15.2:
    /home/kst/local/perl5lib
    /usr/local/apps/perl-blead-2011-09-13-012629Z/lib/site_perl/5.15.2/i686-linux
    /usr/local/apps/perl-blead-2011-09-13-012629Z/lib/site_perl/5.15.2
    /usr/local/apps/perl-blead-2011-09-13-012629Z/lib/5.15.2/i686-linux
    /usr/local/apps/perl-blead-2011-09-13-012629Z/lib/5.15.2
    .


Environment for perl 5.15.2:
    HOME=/home/kst
    LANG=en_US.UTF-8
    LANGUAGE=en_US:en
    LC_COLLATE=C
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/kst/local/bin:/home/kst/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
    PERL5LIB=/home/kst/local/perl5lib
    PERL_BADLANG (unset)
    SHELL=/bin/tcsh

@p5pRT
Copy link
Author

p5pRT commented Oct 13, 2011

From @iabyn

On Wed, Oct 12, 2011 at 03​:25​:45PM -0700, Keith.S.Thompson@​gmail.com wrote​:

use strict;
use warnings;

my $x = -1.0 * 0.0;
my $y = -1.5 * 0.0;

printf "x = $x = %f\n", $x;
printf "y = $y = %f\n", $y;

produces this output​:
x = 0 = 0.000000
y = -0 = -0.000000
[snip]
Further experiment shows that multiplying a negative integral value by
0.0 yields -0.0, but multiplying a negative non-integral value by 0.0
yields 0.0.

On platforms where both floats and ints are 64-bit, perl tries to perform
calculations using integers rather than floats where possible, to
preserve precision. In particular in this case, perl's multiply function,
when presented with the float values -1.0 and 0.0, converts the values to
the int values -1 and 0 and returns the int value 0 (and ints don't have a
signed zero).

--
A power surge on the Bridge is rapidly and correctly diagnosed as a faulty
capacitor by the highly-trained and competent engineering staff.
  -- Things That Never Happen in "Star Trek" #9

@p5pRT
Copy link
Author

p5pRT commented Oct 13, 2011

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

@p5pRT
Copy link
Author

p5pRT commented Oct 13, 2011

@iabyn - Status changed from 'open' to 'rejected'

@p5pRT p5pRT closed this as completed Oct 13, 2011
@p5pRT
Copy link
Author

p5pRT commented Oct 13, 2011

From @deven

On Thu, Oct 13, 2011 at 4​:53 AM, Dave Mitchell <davem@​iabyn.com> wrote​:

On platforms where both floats and ints are 64-bit, perl tries to perform
calculations using integers rather than floats where possible, to
preserve precision. In particular in this case, perl's multiply function,
when presented with the float values -1.0 and 0.0, converts the values to
the int values -1 and 0 and returns the int value 0 (and ints don't have a
signed zero).

Should this be handled as a special case to preserve the -0.0 result?

Deven

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