So when does 0 not equal 0? When it is -0 and even then it depends on who you ask. According the C# specification, -0 is an acceptable value and is treated the same as positive zero in most situations and they seem to be correct because it is very hard to tell that you have a negative 0 value. Take a look at the following set of comparisons:

double zero = 0.0;

double negZero = -0.0;

// following all result in true values

bool areSame = zero.Equals(negZero);

bool areEqual = zero == negZero;

bool sameSign = Math.Sign(zero) == Math.Sign(negZero);

bool sameString = zero.ToString() == negZero.ToString();

When you execute the code above, the results of all the tests is `true`

– that for these tests 0 and -0 are considered the same. However, there are cases where they are not treated the same. For example:

bool sameResult =

Math.Atan2(zero, -1.0) == Math.Atan2(negZero, -1.0);

This is the scenario that Mike, a friend of mine at work, came across the other day. It was a bit more difficult to detect though because the values were coming from variables that were part of a series of calculations. We looked at the value of the variables in the watch window and executed the same method (`Math.Atan2`

) in the watch window explicitly with those values (instead of the variables) and got a different result.

In this particular case, the issue may actually be a bug in that method. We’ve logged it with Microsoft so you can check the status if you’re interested. The point though is that the CLR does support this and that the values could be treated differently. So how can you tell that you are in this situation? One way is to use the `BitConverter.GetBytes`

. If you check the bytes, you will see that the sign bit for the value is actually set indicating that its negative.

byte[] zeroBytes = BitConverter.GetBytes(zero);

byte[] negZeroBytes = BitConverter.GetBytes(negZero);

bool sameBytes = zeroBytes[7] == negZeroBytes[7];

One other interesting point is how you can arrive at this value without explicitly creating a negative zero as I did in the tests above. If you do calculations using doubles, it does not appear that the value will result in a -0. For example:

double one = 1.0d;

double negOne = -one + one;

double posOne = one – one;

byte[] negOneDBytes = BitConverter.GetBytes(negOne);

byte[] posOneDBytes = BitConverter.GetBytes(posOne);

// these both result in positive 0

bool sameSignBit = negOneDBytes[7] == posOneDBytes[7];

In this case, both values are positive 0. However, if you perform the same test with decimal values:

decimal one = 1.0m;

decimal negOne = -one + one;

decimal posOne = one – one;

double dblNegOne = Convert.ToDouble(negOne);

double dblPosOne = Convert.ToDouble(posOne);

byte[] negOneDBytes = BitConverter.GetBytes(dblNegOne);

byte[] posOneDBytes = BitConverter.GetBytes(dblPosOne);

// these have different sign bits

bool sameSignBit = negOneDBytes[7] == posOneDBytes[7];

The sign bit is set for the value that moved from a negative value towards zero and that sign bit is maintained when the value is converted to a double.