Bitwise operations
A number as a set of bits: masks, shifts, and why shifting by 64 changes nothing
Any whole number is a set of bits: 12 is 1100, 10 is 1010. Six op operations work not
with the number as a whole but with each bit separately.
This is needed rarely, but when it is, nothing else will do: several flags in one number, a check for “is this bit on”, a quick multiplication by a power of two.
| Operation | In the block | What it does | 12 and 10 |
|---|---|---|---|
and |
b-and |
a bit stays if it is in both | 8 (1000) |
or |
or |
a bit stays if it is in at least one | 14 (1110) |
xor |
xor |
a bit stays if it is in exactly one | 6 (0110) |
not |
flip |
every bit the other way round | −6 from 5 |
shl |
<< |
shift left: multiply by 2 that many times | 8 from 1 and 3 |
shr |
>> |
shift right: divide by 2 that many times | 1 from 8 and 3 |
The “In the block” column is worth reading carefully: bitwise “and” is labelled b-and,
because and in the list is already taken by the logical “and”, and bitwise inversion is
flip, because not is taken by the “not equal” comparison. This is where the names in
references and the labels on the buttons diverge the most.
The shift is the most understandable of the six: shl 1 3 moves the single bit three places
left and turns 1 into 8. The reverse shr turns 8 back into 1.
Everything is computed in whole numbers, and long ones
Section titled “Everything is computed in whole numbers, and long ones”Before a bitwise operation the number is brought to a whole one: the fractional part is
dropped, so and of 12.7 and 10 gives the same 8 as 12 would.
That whole number is long, 64-bit, and signed — from −2⁶³ to 2⁶³−1.
Three answers nobody expects
Section titled “Three answers nobody expects”shl 1 64 gives 1, not zero. A shift takes only the low six bits of the second number,
that is, the remainder of dividing by 64. A shift by 64 is a shift by 0, a shift by 65 is
a shift by 1. Zero cannot be reached this way at all.
shr −8 1 gives −4, not a huge number. shr is signed: it moves the bits right and pads
the left with the sign, so a negative stays negative. Halving works for minuses too.
ushr −1 60 gives 15. ushr, on the other hand, does not preserve the sign: it treats the
number as unsigned, and to it −1 is 64 one-bits. Shift by 60 and four remain: 15.
What it is for in the game
Section titled “What it is for in the game”The main case is fitting several numbers into one. A processor has plenty of variables, but
few places to put a number for another processor: a memory cell, a unit’s flag. Shifts and or
pack several numbers into one, and shr and and take them back out.
How many fit is decided by that same limit: 53 bits for everything. The details are in the lesson “The number inside”.
Unofficial fan project, not affiliated with Anuke. Mindustry sprites, fonts and translations © Anuke, used under GPL-3.0; Fira Code under OFL-1.1. Site code is GPL-3.0.