We are commanded to "know our primitive types".
The maximum integer representable in Python is a function of the available memory and can be checked with
sys.maxsize. On my 64-bit machine this is 2**63-1. The bounds on floats are specified in
sys.float_info and it turns out that we can represent an astronomically bigger float than an integer - somewhere in the region of 2e289 bigger!
We have already worked with the
6 & 4 is 4, because 110 and 100 share only their leftmost bit (the 4) so all other bits are zeroes.
1 | 2 is 3, because we set to 1 any bit that is 1 in either of the inputs: 01 | 10 == 11.
We have already seen why
8 >> 1 is 4. It's worth knowing that other languages have an unsigned shift operator that doesn't preserve the sign bit of a negative number: I see that in Java
-16 >>> 2 == 1073741820! Perhaps we are safer sticking (in either language to be honest) to
-16 >> 2 which results in the more quickly understandable -4.
1 << 10 shifts our bit 10 places to the left, rather than the right, this time. 2**10 is 1024 and that's what we end up with if we double 1 (2**0) ten times.
~ operator produces the complement of its operand - every 0 becomes a 1, every one a zero.
~0 is -1. Maybe see the companion blog post about Two's Complement if this seems peculiar.
^ operator is the bitwise exclusive or (XOR). Essentially
x ^ y compares bits and results in 1 if the bits are different (if x is 1 or y is 1 but not if both x and y are 1).