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 `&`

operator. `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.

The `~`

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.

The `^`

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).