简体   繁体   中英

What is the difference between 0 and -0 floating point value?

This code snippet in Visual Studio 2013:

double a = 0.0;
double b = -0.0;

cout << (a == b) << " " << a << " " << b;

prints 1 0 -0 . What is the difference between a and b ?

C++ does not guarantee to differentiate between +0 and -0. This is a feature of each particular number representation. The IEEE 754 standard for floating point arithmetic does make this distinction, which can be used to keep sign information even when numbers go to zero. std::numeric_limits does not directly tell you if you have possible signed zeroes. But if std::numeric_limits<double>::is_iec559 is true then you can in practice assume that you have IEEE 754 representation , and thus possibly negative zero.


Noted by “gmch” in a comment , the C++11 standard library way to check the sign of a zero is to use std::copysign , or more directly using std::signbit , eg as follows:

#include <iostream>
#include <math.h>       // copysign, signbit

using namespace std;

auto main() -> int
{
    double const z1 = +0.0;
    double const z2 = -0.0;

    cout << boolalpha;
    cout << "z1 is " << (signbit( z1 )? "negative" : "positive") << "." << endl;
    cout << "z2 is " << (signbit( z2 )? "negative" : "positive") << "." << endl;
}

Without copysign or signbit , eg for a C++03 compiler, one way to detect a negative zero z is to check whether 1.0/z is negative infinity, eg by checking if it's just negative.

#include <iostream>
using namespace std;

auto main() -> int
{
    double const z1 = +0.0;
    double const z2 = -0.0;

    cout << boolalpha;
    cout << "z1 is " << (1/z1 < 0? "negative" : "positive") << "." << endl;
    cout << "z2 is " << (1/z2 < 0? "negative" : "positive") << "." << endl;
}

But while this will probably work in practice on most any implementation, it's formally * Undefined Behavior.

One needs to be sure that the expression evaluation will not trap.


*) C++11 §5.6/4 “If the second operand of / or % is zero the behavior is undefined”

See http://en.m.wikipedia.org/wiki/Signed_zero

In a nutshell, it is due to the sign being stored as a stand-alone bit in IEEE 754 floating point representation. This leads to being able to have a zero exponent and fractional portions but still have the sign bit set--thus a negative zero. This is a condition that wouldn't happen for signed integers which are stored in twos-complement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM