"10239472" is 8 bytes, but 10239472 is just 4 ,_,
(O,O)
( )
-"-"-
0b prefixprint(0b101101) # (1 * 32) + (1 * 8) + (1 * 4) + 1
45
print(0x2D) # (2 * 16) + 13
45
0100 is 41100 is -4| Base 10 | Base 2 |
|---|---|
| 3 | 011 |
| 2 | 010 |
| 1 | 001 |
| 0 | 000 |
| -1 | 111 |
| -2 | 110 |
| -3 | 101 |
| -4 | 100 |
Can still determine sign by looking at the first bit
But two's complement is asymmetric
No positive number to match the largest negative number
Operate on corresponding bits in representation
& (and) is 1 if both bits are 1, 0 otherwise
0b1100 & 0b1010 == 0b1000
12 & 10 == 8
| (or) is 1 if either bit is 1, 0 otherwise
0b1100 | 0b1010 == 0b1110
12 | 10 == 14
| Expression | Bitwise | Result (bits) | Result (decimal) |
|---|---|---|---|
12 & 6 |
1100 & 0110 |
0100 |
4 |
12 | 6 |
1100 | 0110 |
1110 |
14 |
12 ^ 6 |
1100 ^ 0110 |
1010 |
10 |
~ 6 |
~ 0110 |
1001 |
9 |
12 << 2 |
1100 << 2 |
110000 |
48 |
12 >> 2 |
1100 >> 2 |
0011 |
3 |
Take a closer look at ~6
We are using two's complement, so 6 is 0b000…00110
Its bitwise negation is 0b111…11001, which is -7
Shifting up and down is almost like multiplying or dividing by 2
But what if the top bit changes?
0b1111 >> 1 is 0b0111, so -1/2 is 7struct Moduleimport struct
fmt = "ii" # two 32-bit integers
x = 31
y = 65
binary = struct.pack(fmt, x, y)
print("binary representation:", repr(binary))
normal = struct.unpack(fmt, binary)
print("back to normal:", normal)
binary representation: b'\x1f\x00\x00\x00A\x00\x00\x00'
back to normal: (31, 65)
Not all bytes correspond to common characters
So Python uses two-digit hex representation \xPQ
\x00 is a null byte (value 0)
Easy to miss the actual A between one \x00 and the next
from struct import pack
print(pack("3i", 1, 2, 3))
print(pack("5s", bytes("hello", "utf-8")))
print(pack("5s", bytes("a longer string", "utf-8")))
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
b'hello'
b'a lon'
text = "hello"
print(f"{len(text)}s")
5s
Pack strings as a fixed-size count and that many bytes
Use bytes to convert character string to bytes
def pack_string(as_string):
as_bytes = bytes(as_string, "utf-8")
header = pack("i", len(as_bytes))
format = f"{len(as_bytes)}s"
body = pack(format, as_bytes)
return header + body
if __name__ == "__main__":
result = pack_string("hello!")
print(repr(result))
b'\x06\x00\x00\x00hello!'
def unpack_string(buffer):
header, body = buffer[:4], buffer[4:]
length = unpack("i", header)[0]
format = f"{length}s"
result = unpack(format, body)[0]
return str(result, "utf-8")
buffer = pack_string("hello!")
result = unpack_string(buffer)
print(result)
hello!
0b11101101:1101 is the first four bits of the character10result = pack_string("こんにちは!")
print(repr(result))
b'\x10\x00\x00\x00\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\x \
e3\x81\xaf!'
open(filename, "r") converts bytes to characters\r\n to Unix \nopen(filename, "rb") to read in binary mode