Nailing the Point Down
Fix the point at an agreed scale and a fraction becomes an ordinary whole number, which the machine adds at full speed.
Unit 4 left us with a problem. Floating-point carries any fraction you like, approximately, and on these machines it is far too slow for a game loop.
So games did the opposite. They fixed the point instead of floating it.
Agree on a scale
Pick a scale, say 256, and agree once and for all that every number you store is that many 256ths.
Then 1.5 is not stored as “1.5” at all. It is stored as 1.5 × 256, which is 384. That is an ordinary whole number.
To read the real value back, divide by the agreed scale:
SHOW 384 / 256
1.5
The point is not floating. It is fixed at “divide by 256”, and everyone who touches the value agrees to it.
The fraction is being carried as a whole number. That is the trick, and it is also the name: fixed-point.
The maths is just integer maths
Here is why that is such a win. Fixed-point values are whole numbers, so you do arithmetic on them with plain integer addition, which is the fast kind.
Add 1.5 and 0.5. Store both scaled, as 384 and 128, then add the integers:
SHOW 384 + 128
512
512 is 2 at our scale, so 1.5 + 0.5 came to 2 using nothing but whole-number addition.
The scale is a shift
Scaling by 256 is not even a multiplication.
256 is 2⁸, so multiplying by 256 is a shift left by eight, and dividing by 256 is a shift right by eight. Both come straight from Unit 2.
So fixed-point is built from the two fastest things the machine does: integer arithmetic and shifting. That is the whole reason it won.
What it costs you
Fixed-point is not free. Two things are now your job rather than the machine’s.
You remember the scale. The machine sees 384 and thinks 384. Only you know it means 1.5.
You keep the scales matching. Every value in a sum has to share one scale, or the answer is nonsense.
That bookkeeping buys speed. In a game moving dozens of objects fifty times a second, it was the trade worth making, every time.
Choosing the scale
The scale decides what you get and what you give up.
A bigger scale buys finer fractions. At ×256 you can hold 256ths, which is far finer than a pixel.
It costs range. At ×256 the largest value you can hold is 256 times smaller than the raw integer’s limit. Choose the scale to fit the job.
When it’s wrong, see why
- A value printed as a big whole number, like 384 rather than 1.5. You forgot to divide by the scale. The machine only ever sees integers.
- Two values fought. Adding a ×256 number to a ×16 number gives nonsense. Everything in a sum must share the same scale.
- The numbers ran out of room. A scale eats range, so a value that fitted as a plain integer may not fit once scaled.
- A fraction vanished. Scaled values are still whole numbers, so anything finer than one unit of your scale rounds away.
What you’ve learnt
- Fixed-point stores a fraction as a whole number at an agreed scale.
- Its arithmetic is plain integer addition, and its scaling is a shift.
- You carry the bookkeeping: remembering the scale, and keeping every value in a sum on the same one.
- Games chose it because in a loop, speed won.
Where this leaves you
That is the primer. You can look at a number the way the machine does, whole or fractional, positive or negative, in bits or in hex, and you can mask it, shift it and scale it.
From here the road goes down into a real machine, where hex addresses, bit flags, signed offsets and fixed-point are not background facts. They are the language the code is written in.