4

I can't get my head around these exponents:

  • Why is exponent 0000 0000 = -126 instead of -127 (i.e. 0 - 127)?
    • What is the exact value of exponent 1111 1111?
    • Why does 0 1111 1111 0000 0000 0000 0000 0000 000 equal infinity?

I'm very new to all this, so please explain in simple lay terms! Thanks!

Super Jade
  • 5,609
  • 7
  • 39
  • 61
doctopus
  • 5,349
  • 8
  • 53
  • 105

2 Answers2

8

Why is exponent 0000 0000 = -126 instead of -127 (i.e. 0 - 127)?

For most normal exponents, when we reach the bottom of the significand range, we step down to the next exponent. For example, the representable numbers from 1 (inclusive) to 2 (exclusive) are, in descending order:

  • 1.11…111 • 20,
  • 1.11…110 • 20,
  • 1.11…101 • 20,
  • 1.11…100 • 20,
  • 1.00…011 • 20,
  • 1.00…010 • 20,
  • 1.00…001 • 20,
  • 1.00…000 • 20.

Then, when going to the next lower numbers, we adjust the exponent, so the next lower numbers are:

  • 1.11…111 • 2−1,
  • 1.11…110 • 2−1,
  • 1.11…101 • 2−1,
  • 1.11…100 • 2−1,

Now, when we are at the lowest normal exponent, the lowest numbers in this range are:

  • 1.00…011 • 2−126,
  • 1.00…010 • 2−126,
  • 1.00…001 • 2−126,
  • 1.00…000 • 2−126.

In order to keep going at this point, it was decided the final step would be to change the leading bit to 0 instead of 1. There was a choice here: Numbers with a zero in the exponent field could continue the pattern, going on to exponent −127, so the next representable number would be 1.11…111 • 2−127, or they could stick at exponent −126 but change the leading bit to 0 instead of 1.

If the pattern had continued, then, for example, 1.11…111 • 2−127 and 1.11…110 • 2−127 would both be representable numbers, but their difference, 0.00…001 • 2−127 = 1 • 2−150, would not be representable. So, if x and y were these numbers, their computed difference, x-y, would have to be 0 due to rounding (when rounding to the nearest representable value). However, sometimes people wrote code like this:

if (x == y)
    Handle special case.
else
    Handle normal case with some calculation involving division by x-y.

So continuing the exponent pattern to −127 would break some code and cause floating-point arithmetic to act in undesired ways. So, the choice was made to break the pattern, keep the exponent at −126, and make the leading bit 0 instead of 1. Then the next representable numbers are:

  • 0.11…111 • 2−126,
  • 0.11…110 • 2−126,
  • 0.11…101 • 2−126,
  • 0.11…100 • 2−126,
  • 0.00…011 • 2−126,
  • 0.00…010 • 2−126,
  • 0.00…001 • 2−126,
  • 0.00…000 • 2−126.

You can see that we want 0.11…111 • 2−126 just after 1.00…000 • 2−126. If it were 0.11…111 • 2−127 instead, there would be a gap—that is half the size it needs to be.

What is the exact value of exponent 1111 1111?

When the exponent field is 1111 1111, it does not represent any numeric exponent for the normal floating-point format. That value in the exponent field is a code for special values (infinity and NaN).

Why does 0 1111 1111 0000 0000 0000 0000 0000 000 equal infinity?

There is not a mathematical reason for this. Infinity does not arise out of any mathematics performed on the significand and the exponent. It was just decided that the exponent field 1111 1111 would represent infinities and NaNs, and that, when the significand field is all zeros, it represents infinities, and, when the significand field is not all zeros, it represents a NaN.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I catch most of what you wrote, but do have one question: after 1.00…000 • 2^-126, why cant you have 1.11…111 • 2^-127 instead of 0.11…111 • 2^-126? – doctopus Sep 03 '18 at 02:33
  • Because you'd still have a big gap, between +/-`1.0*2^-127`. By leaving its exponent at `2^-126`, the denormal numbers exactly fill the gap between +/-`1.0*2^126`, including the actually quite important representation for `0`. – comingstorm Sep 03 '18 at 03:44
  • @doctopus: 1.11…111 • 2^-127 is closer to the previous (bigger) number than 0.11…111 • 2^-126 is, but note it was stated earlier that we decided to change the leading bit to 0 instead of decreasing the exponent. The reason for that decision was not to decrease the gap size at that point but rather for the arithmetic properties it produces. If we just decreased the exponent to −127, the next step after that has to be to go to zero, because we are out of exponents. Then there would exist different numbers whose subtraction produced zero… – Eric Postpischil Sep 03 '18 at 12:13
  • … And that can break some code that people write, such as `if (x != y) { do some calculations that involve dividing by x-y }`. For example, subtracting 1.11…111 • 2^-127 and 1.11…110 • 2^-127 is mathematically 1 • 2^−150, but that cannot be represented, so it has to be rounded to zero. By having the exponent code of 0 represent exponent −126 with leading bit 0, the results of all subtractions of different numbers are non-zero. E.g., 0.11…111 • 2^-126 minus 0.11…110 • 2^-126 is 0.00…001 • 2^-126. I will edit this into the answer when I have more time. – Eric Postpischil Sep 03 '18 at 12:16
5

The exponent bias for a single-precision float is 127. This means that an exponent value of 127 (1000 0000) is evaluated as an actual exponent of zero, and an exponent value of one (0000 0001) is evaluated as an actual exponent of -126.

Exponent values of all zero bits or all one bits (0000 0000 or 1111 1111) are not actual exponents, but instead trigger special case behavior. An all-zero exponent means there is no implied leading one bit in the mantissa; this is used for subnormal numbers. And an all-one exponent is used to mark that the value is either infinity, negative infinity, or NaN, depending on the sign bit and mantissa bits.

For further reading, The Floating Point Guide has a nice explanation in easy terms, and of course if you really want the nitty-gritty, nothing beats Goldberg's paper.

Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135