Previously, we’d talked in depth about floating point format, specifically the IEEE floating
point specification for 32 bit numbers, and the bitwise representation of them.
So we have the sign, mantissa and the exponent.
And the mantissa is always represented as 1.
the actual value that’s stored in the mantissa.
The 1 before the binary point is implied and we never store that, so that the number is
always normalized.
But this gives rise to a tricky situation.
If the value of the mantissa is always 1 point something, then how do we represent zero?
That’s where the special conditions come in.
I’d mentioned as well in the previous video, that 2 states of the exponents were reserved
for these special conditions.
All zeros and all one, and we could utilize the rest of the states for actually representing
the exponent.
If all bits of the exponent are zero, and if all the bits of the mantissa are zero as
well, then this combination is represented as the number zero.
It doesn't matter what the sign bit is, it can be negative or positive, but the floating
point processor disregards this, and considers the number to be zero.
Let's look at a couple of scenarios where we need to express a certain concept in mathematics,
but it cannot be expressed as a definitive number.
What happens when we divide something by zero.
If you were to perform integer division by zero, programming languages tend to throw
exceptions, stating that division by zero is illegal.
But you can also argue that the result of division by zero tends towards infinity.
So infinity is a concept in mathematics that can’t be defined as a precise number, but
rather as a concept.
And in floating point numbers you can express this.
If all the bits of the exponent are set to 1, and if all the bits of the mantissa are
set to zero, then this results in the floating point number being interpreted as infinity.
Another possible category of result that can be formed are invalid numbers, calculations
that are illegal for floating point numbers, and results in numbers which are either undefined
or aren’t real numbers.
These are results from operations like zero divided by zero, which is truly undefined.
Or operations like the square root of a negative number, which you could argue results in an
imaginary number, but this isn’t in the set of real numbers, so it’s an illegal
value and cannot be represented in the floating point format.
The way you represent this is by setting all the exponent bits to 1, and having any combination
of the mantissa, other than it all being zeros, because, when mantissa is all zeros, the number
is infinity.
So this representation is called NaN, or not a number.
Let’s check some of these conditions out with a little bit of c++.
Again, the language doesn’t really matter here.
The behaviour of these operations will be the exact same across all languages which
adopt the IEEE floating point standard, , which pretty much all of the popular languages do.
And across all underlying hardware as well.
IEEE floating point format is the de facto standard.
So, I’ve got variables one and zero, set to floating point 1 and 0.
Let’s look at a non-zero number divided by zero and a zero divided by zero.
The result of 1 divided by zero is infinity like we discussed.
And the result of 0 divided by 0 is this weird representation, - NaN and ind in brackets.
IND stands for indeterminate number.
And NaN is not a number.
There are certain computations whose result cannot be determined by the floating point
unit and they’re marked as IND, but for all practical purposes, it’s not a number.
The result of the square root of negative 1 is again, not a number.
You can build nan’s and inf’s using these sorts of expressions, or you can manually
bitset them to what the compiler expects a floating point number to be.
But, there are utility methods to give you these values, and they’re in the limits
header, and they’re all static functions under the numeric_limits class.
I can initialize Inf and NaN using these functions.
Now, there are certain properties on infinities and nans that are probably worth knowing.
Checkout these statements here.
They are all involving infinities.
You are adding infinity to an arbitrary number, inf + inf, inf - inf, inf * inf, inf / inf,
inf * 0, inf / 0, and then are 2 inf equal.
This last statement is a comparison between two different infinities, and we’ll see
what the result is.
But before that, just try to put some values into what you think the results would be.
Let’s go.
So yea, operations of infinites either result in infinity or not a number, and no, you don’t
need to remember any of this.
No self respecting developer would intentionally write any of these statements.
Your intermediate calculations could possibly end up with one of these operations, but the
output of such calculations would probably not be very useful.
So let's quickly look at some operations on NaN.
Same drill as before, I’ll just print these out.
So you can see operations on NaN always result in NaN. and the equality comparison between
2 NaN would always result in false.
So let’s go back to the list of special conditions we’ve seen in this video.
You can see that there’s one condition that’s possibly missing.
What happens when the exponent is all zero and the mantissa isn’t all zeros.
I’ve deliberately excluded this till the end, because this is not a very easy topic
to talk about, and probably something that you wouldn’t encounter very often.
But it’s something that you need to know, and when you do encounter it and all the weird
behaviour that follows it, you’ll be equipped to diagnose and handle those cases.
Welcome to the world of subnormal numbers.