Is minus zero (-0) equivalent to zero (0) in C#?
It sounds like you're looking for the edge cases where they aren't interchangeable, so here are some examples.
object.Equals on structs> 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.SignDespite 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.MaxA 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".