Is it possible to differentiate between 0 and -0?

I know that the integer values 0 and -0 are essentially the same. But, I am wondering if it is possible to differentiate between them.

For example, how do I know if a variable was assigned -0?

bool IsNegative(int num)
{
    // How ?
}

int num = -0;
int additinon = 5;

num += (IsNegative(num)) ? -addition : addition;

Is the value -0 saved in the memory the exact same way as 0?


Solution 1:

It depends on the machine you're targeting.

On a machine that uses a 2's complement representation for integers there's no difference at bit-level between 0 and -0 (they have the same representation)

If your machine used one's complement, you definitely could

0000 0000   -> signed   0 
1111 1111   -> signed   −0

Obviously we're talking about using native support, x86 series processors have native support for the two's complement representation of signed numbers. Using other representations is definitely possible but would probably be less efficient and require more instructions.

(As JerryCoffin also noted: even if one's complement has been considered mostly for historical reasons, signed magnitude representations are still fairly common and do have a separate representation for negative and positive zero)

Solution 2:

For an int (in the almost-universal "2's complement" representation) the representations of 0 and -0 are the same. (They can be different for other number representations, eg. IEEE 754 floating point.)

Solution 3:

Let's begin with representing 0 in 2's complement (of course there exist many other systems and representations, here I'm referring this specific one), assuming 8-bit, zero is:

0000 0000

Now let's flip all the bits and add 1 to get the 2's complement:

1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000

we got 0000 0000, and that's the representation of -0 as well.

But note that in 1's complement, signed 0 is 0000 0000, but -0 is 1111 1111.

Solution 4:

I've decided to leave this answer up since C and C++ implementations are usually closely related, but in fact it doesn't defer to the C standard as I thought it did. The point remains that the C++ standard does not specify what happens for cases like these. It's also relevant that non-twos-complement representations are exceedingly rare in the real world, and that even where they do exist they often hide the difference in many cases rather than exposing it as something someone could easily expect to discover.


The behavior of negative zeros in the integer representations in which they exist is not as rigorously defined in the C++ standard as it is in the C standard. It does, however, cite the C standard (ISO/IEC 9899:1999) as a normative reference at the top level [1.2].

In the C standard [6.2.6.2], a negative zero can only be the result of bitwise operations, or operations where a negative zero is already present (for example, multiplying or dividing negative zero by a value, or adding a negative zero to zero) - applying the unary minus operator to a value of a normal zero, as in your example, is therefore guaranteed to result in a normal zero.

Even in the cases that can generate a negative zero, there is no guarantee that they will, even on a system that does support negative zero:

It is unspecified whether these cases actually generate a negative zero or a normal zero, and whether a negative zero becomes a normal zero when stored in an object.

Therefore, we can conclude: no, there is no reliable way to detect this case. Even if not for the fact that non-twos-complement representations are very uncommon in modern computer systems.

The C++ standard, for its part, makes no mention of the term "negative zero", and has very little discussion of the details of signed magnitude and one's complement representations, except to note [3.9.1 para 7] that they are allowed.

Solution 5:

If your machine has distinct representations for -0 and +0, then memcmp will be able to distinguish them.

If padding bits are present, there might actually be multiple representations for values other than zero as well.