Zero Equals What???

Last time I asked you what the output would be from this code….

try
{
	checked
	{
		double zero = 0;
		double minus = -1.0e-400;
		double big = 1.0 / zero;
		double minusBig = 1.0 / minus;

		Console.WriteLine(zero == minus);
		Console.WriteLine(big == minusBig);
	}
}
catch (Exception ex)
{
	Console.WriteLine(ex.Message);
}

Did you think that because I’m dividing by zero (in the statement that declares big), the whole thing would throw an exception? If so then I apologize for being devious. The whole try…catch block in the code was designed to separate the men from the boys. Doubles are floating point values. Infinity is a valid value for a floating point, and it’s perfectly fine to divide a floating point by zero. The result is infinity. And that checked block is there to fool you too – it has no impact on this code. Dividing a floating point by zero will give a valid result whether or not you’re in a checked block.

So – there’s no exception, and you can completely ignore both the try…catch block and the checked block.

In fact this is the output.

ZeroEqualsWhat_Result

The interesting question is why you get true then false.

The first Console.WriteLine looks like it would be comparing 0 and minus 10 to the power minus 400. Mathematically that looks like it should be false so the first true in the output looks idiotic. The key is that the smallest number that can be stored in a double is in fact around 5 times 10 to the minus 324. It is not possible to store 10 to the minus 400 in a double, so the compiler has to pick the closest approximation that can be stored in a double. In fact, 10 to the minus 400 is way way smaller than 5 times 10 to the minus 324. This picture shows roughly where the numbers lie on the number line, and it should be obvious from it that the closest available approximation that can be stored is a big fat zero.

ZeroEqualsWhat_

Hence the variable minus contains zero. So the expression zero == minus is just comparing 0 with 0 which is obviously true. And by the way, that’s a reminder that comparing floating point numbers for equality is BAD, Do not do it. As this code shows, it will frequently give you results that you probably didn’t expect.

So if the variable zero equals the variable minus, then surely dividing one by the contents of zero should yield exactly the same result as dividing one by the contents of minus, and the second Console.WriteLine ought to write out true too?

Not so.

The try block was there to separate the boys from the men. This next point is to separate the mere men from the strong muscly superhero real men. The thing I accidentally-deliberately forgot to mention was that floating point numbers have separate representations for zero and minus zero. The variable zero will contain 0 (or +0). The variable minus also contains 0, but because the compiler knows it’s trying to approximate a negative number, it’ll store this as -0. 0 always equals -0 – so far they are just two ways of representing the same number. But the minus sign is very important when you divide one by them. One divided by 0 is infinity, and one divided by -0 (minus zero) is minus infinity. And infinity is most definitely not equal to minus infinity. Which is why the second Console.WriteLine() is false.

Just to prove I’m not making this up, here’s a screenshot of Visual Studio, stopped in the debugger running this code. You can see the values of the variables in the watch window.

ZeroEqualsWhat_Locals

And yes, floating points are subtle.

Advertisements

Comment on this article (your first comment on TechieSimon will be moderated)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s