Every integer, in both directions, is now yours. So write down one half. Then one third. Then one tenth.
Before that, three programs.
#include <stdio.h> int main(void) { double a = 0.1; double b = 0.2; if (a + b == 0.3) printf("equal\n"); else printf("not equal\n"); return 0; }
Write your answer down before anybody runs it.
#include <stdio.h> int main(void) { float x = 16777216.0f; printf("%.0f\n", x); printf("%.0f\n", x + 1.0f); return 0; }
That number is 224. It is nowhere near the limit of what a float can hold.
#include <stdio.h> int main(void) { float y = 16777218.0f; printf("%.0f\n", y); printf("%.0f\n", y + 1.0f); return 0; }
This one is 224 + 2. Adding one to it should be uneventful.
A number system where adding one changes nothing, and then adding one to a slightly bigger number changes it by two.
Talk to the person next to you. What sort of thing behaves like that?
Almost every digit on this slide is a zero, and not one of those zeros is telling you anything.
Write the digits that carry information, then say separately how big the number is.
Slide the exponent. The digits never change. Only the statement of scale does.
Four significant figures on the distance to the sun means you are certain to about ten million metres.
Four significant figures on the atom means you are certain to about a hundred-millionth of a nanometre.
The same promise. Wildly different absolute error.
The gap between numbers you can write down is not fixed. It grows with the number.
6.371 × 106 and 63.71 × 105 are the same number written two ways.
Pick one, so that every number has exactly one spelling. That is what normalised means.
Remember this rule. In binary it is about to hand us a free bit.
Columns to the right of the point are worth a half, a quarter, an eighth, and onwards, exactly as the columns to the left are worth one, two, four.
Then shift until there is a single one before the point, and count how far you shifted.
It could be a 1, or a 4, or a 9. You have to write it down.
In base two there is only one digit it can possibly be.
So do not store it.
Everybody agrees it is there. Twenty three bits of storage give you twenty four bits of number, for nothing.
Thirty two wires, cut into three fields by nothing more than an agreement about which wire means what.
Zero means positive, one means negative. That is the entire field.
It is sign and magnitude, the scheme we threw out last session for having two zeros.
And it still has two zeros. Floats have a positive zero and a negative zero, and they are different patterns.
Here it is the right choice anyway. Negating a float costs one inverter and never disturbs the digits. We will pay for the two zeros in the next session.
Eight bits give 256 patterns. The scale needs to go both ways, so subtract 127 from whatever is stored.
Which would give a range of −127 to +128. Except two patterns never get used as exponents at all.
| 00000000 | reserved |
| 00000001 | −126 |
| 01111111 | 0 |
| 11111110 | +127 |
| 11111111 | reserved |
Usable range: 2−126 to 2127, which is about 10−38 to 1038.
All zeros and all ones are set aside. Sixteen million patterns each, spent on something that is not a number. That is next session.
Twenty three stored bits, plus the hidden leading one, gives 24 binary digits of precision.
So the smallest step you can take is one unit in the last of those 24 places.
The step is always about one part in eight million of whatever you are standing on. Never a fixed amount.
| as hex | 0x3F800000 |
| value | 1 |
| exactly | 1 |
| family | normal |
| next float up | 1.00000012 |
| the gap there | 1.1920929e-7 |
Not a rounding error in the printing. That is the exact value of the number in the register, written out in full.
One tenth is not a sum of halves, quarters and eighths. In binary it repeats forever, and twenty four digits is where we stop.
Program one, explained.
There is no float between them. Ask for one and you get the nearest one that exists, and nothing tells you it happened.
A ruler has evenly spaced marks. Between any two of them, the same distance.
Half of all the floats there are live between zero and two. The other half are spread across everything else.
It is dense where you usually work and threadbare where you rarely go,
which is exactly what you want, and it is why nobody warns you when you leave the dense part.
One. One tenth has no exact spelling in twenty four binary digits, so two roundings landed somewhere a third rounding did not.
Two. At 224 the gap between floats is two. Adding one lands halfway, and it rounded back.
Three. Same gap of two. Adding one landed halfway again, and this time it rounded the other way, to the even one.
Nothing went wrong. Everything did exactly what it promised.
All zeros, and all ones. Thirty three million patterns, held back for something.
Next session, what they bought.