Is minus zero (-0) equivalent to zero (0) in C#?
Signed zero is zero with an associated sign. In ordinary arithmetic, the number 0 does not have a sign, so that −0, +0 and 0 are identical.
There's no such thing as negative zero. For a binary integer, setting the sign bit to 1 and all other bits to zero, you get the smallest negative value for that integer size. (Assuming signed numbers.) Negative zero is actually used in mathematical analysis, especially in limit calculations.
1 and –1are the rational numbers that are equal to their reciprocals. (iii). 0 is the rational number that is equal to its negative. Hence our answer is, 0 is the rational number that is equal to its negative.
Zero, 0, is neither positive nor negative.
For integers, there is no binary representation that makes a difference between 0 and -0, so they are by definition equal.
For IEEE floating-point numbers, there is a distinction of negative and positive zero. I made some tests (CLR of .NET Framework 2.0, C# 3) and it seems that they are considered equal, which is actually the behavior expected according to the IEEE 754 standard.
Here's my test code to show that:
double minusOne = -1.0; double positiveZero = 0.0; double negativeZero = minusOne*positiveZero; Console.WriteLine("{0} == {1} -> {2}", positiveZero, negativeZero, positiveZero == negativeZero); Console.WriteLine("Binary representation is equal: {0}", BitConverter.DoubleToInt64Bits(positiveZero) == BitConverter.DoubleToInt64Bits(negativeZero));
Returns:
0 == 0 -> True Binary representation is equal: False
It sounds like you're looking for the edge cases where they aren't interchangeable, so here are some examples.
object.Equals
on struct
s> struct SomeStruct { public double X; } > var a = new SomeStruct { X = 0d }; > var b = new SomeStruct { X = -0d }; > a.Equals(b) false >
> 1/0d ∞ > 1/-0d -∞ >
Any type of explicit byte-wise or bit-wise deconstruction, of course, or type punning. These examples are from a PC:
> BitConverter.GetBytes(0d) byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 } > BitConverter.GetBytes(-0d) byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 } >
Math.Sign
Despite what you might expect, Math.Sign
does not distinguish between negative and positive zero. It only tells you whether a number is equal to, greater than, or less than 0.
> Math.Sign(-0f) 0
Math.Min
and Math.Max
A few arithmetic operations have edge cases for -0. One interesting one is Math.Min
(and equivalently for max), which is that when comparing signed zeros it returns the second one. So:
> BitConverter.GetBytes(Math.Min(0.0, -0.0)) byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 } > BitConverter.GetBytes(Math.Min(-0.0, 0.0)) byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 } >
decimal
representationsThe decimal
type doesn't have a negative 0 per se, but it does have multiple binary representations for zero:
> new decimal(new int[4] { 0, 0, 0, 0 }) 0 > new decimal(new int[4] { 0, 0, 0, -2147483648 }) 0 >
The second example there could be considered a negative zero because it's bitwise-identical to the regular zero except with the negation bit set. But as far as the formatter's concerned it's just a zero. There are, in fact dozens of zero representations for decimal
, for different decimal point shifts, all of which are arithmetically equivalent and display as 0:
> new decimal(new int[4] { 0, 0, 0, 131072 }) 0.00 > new decimal(new int[4] { 0, 0, 0, 1835008 }) 0.0000000000000000000000000000 > new decimal(new int[4] { 0, 0, 0, 65536 }) 0.0
That said, you'll only be able to distinguish them from each other by binary-comparison or binary-conversion means. From just experimentation, it seems that the struct
trick above doesn't work on them. Math.Min
returns whichever zero was given second.
Certain patterns of bits in float
and double
types represent subnormal (aka denormal) values. I won't go into what they are—see the link instead—but the important thing to know is that the CLI spec explicitly declares their operations as implementation-specific. I don't know that there are platforms that treat them as 0, but there could be. On the other hand, The C# Programming Language says that they're "considered valid non-zero values".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With