| prev | Version 1107 (Mon Nov 27 20:46:05 2006) | next |
"10239472" is 8 bytes long, but the 32-bit integer it represents is 4 bytes"34" to the one represented by "57"![[Two's Complement]](./img/binary/twos_complement.png)
Figure 18.1: Two's Complement
| Name | Symbol | Purpose | Example |
|---|---|---|---|
| And | & | 1 if both bits are 1, 0 otherwise | 0110 & 1010 = 0010 |
| Or | | | 1 if either bit is 1 | 0110 & 1010 = 1110 |
| Xor | ^ | 1 if the bits are different, 0 if they're the same | 0110 & 1010 = 1100 |
| Not | ~ | Flip each bit | ~0110 = 1001 |
| Table 18.1: Bitwise Operators in Python | |||
def format_bits(val, width=1):
'''Create a base-2 representation of an integer.'''
result = ''
while val:
if val & 0x01:
result = '1' + result
else:
result = '0' + result
val = val >> 1
if len(result) < width:
result = '0' * (width - len(result)) + result
return result
tests = [
[ 0, None, '0'],
[ 0, 4, '0000'],
[ 5, None, '101'],
[19, 8, '00010011']
]
for (num, width, expected) in tests:
if width is None:
actual = format_bits(num)
else:
actual = format_bits(num, width)
print '%4d %8s %10s %10s' % (num, width, expected, actual)
0 None 0 0 0 4 0000 0000 5 None 101 101 19 8 00010011 00010011
x << Nand, or, and not to set specific bits to 1 or 0x to 1:mask in which bit i is 1 and all others are 0x = x | maskx to 0:mask in which bit i is 1 and all others are 0~, so that the ith bit is 0, and all the others are 1x = x & mask![[Setting and Clearing Bits]](./img/binary/setting_clearing_bits.png)
Figure 18.2: Setting and Clearing Bits
![[Using Bits to Record Sets of Flags]](./img/binary/bit_flags.png)
Figure 18.3: Using Bits to Record Sets of Flags
# hex binary
MERCURY = 0x01 # 0001
PHOSPHORUS = 0x02 # 0010
CHLORINE = 0x04 # 0100
# Sample contains mercury and chlorine
sample = MERCURY | CHLORINE
print 'sample: %04x' % sample
# Check for various elements
for (flag, name) in [[MERCURY, "mercury"],
[PHOSPHORUS, "phosphorus"],
[CHLORINE, "chlorine"]]:
if sample & flag:
print 'sample contains', name
else:
print 'sample does not contain', name
sample: 0005 sample contains mercury sample does not contain phosphorus sample contains chlorine
![[Uneven Spacing of Floating-Point Numbers]](./img/binary/uneven_spacing.png)
Figure 18.5: Uneven Spacing of Floating-Point Numbers
f.read(N) reads (up to) next N bytesf is empty, returns Nonef.write(str) writes the bytes in the string strinput = open(filename, 'rb') (and similarly for output)"\r\n" to Unix-style "\n"…"r", then in "rb"import sys
print sys.platform
for mode in ('r', 'rb'):
f = open('open_binary.py', mode)
s = f.read(40)
f.close()
print repr(s)
cygwin 'import sys\r\nprint sys.platform\r\nfor mode'
linux 'import sys\nprint sys.platform\nfor mode in '
fwrite(&array, sizeof(int), 3, file) will write 3 4-byte integers to a file![[C Storage vs. Python Storage]](./img/binary/c_vs_python_storage.png)
Figure 18.6: C Storage vs. Python Storage
![[Packing Data]](./img/binary/pack_data.png)
Figure 18.7: Packing Data
struct module to pack and unpackpack(fmt, v1, v2, …) packs the values v1, v2, etc. according to fmt, returning a stringunpack(fmt, str) unpacks the values in str according to fmt, returning a tupleimport struct fmt = 'hh' # two 16-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: '\x1f\x00A\x00' back to normal: (31, 65)
'\x1f\x00A\x00'?['\x1f', '\x00', 'A', '\x00']"A" is 6510| Format | Meaning |
|---|---|
"c" | Single character (i.e., string of length 1) |
"B" | Unsigned 8-bit integer |
"h" | Short (16-bit) integer |
"i" | 32-bit integer |
"f" | 32-bit float |
"d" | Double-precision (64-bit) float |
"2" | String of fixed size (see below) |
| Table 18.2: Packing Format Specifiers | |
"4i" is four integers"B" or "h" instead of the full 32"4s" for a 4-character stringunpack know how much data to use?calcsize(fmt) calculates how large (in bytes) the data produced using fmt will beimport struct
packed = struct.pack('4c', 'a', 'b', 'c', 'd')
print 'packed string:', repr(packed)
left16, right16 = struct.unpack('hh', packed)
print 'as two 16-bit integers:', left16, right16
all32 = struct.unpack('i', packed)
print 'as a single 32-bit integer', all32[0]
float32 = struct.unpack('f', packed)
print 'as a 32-bit float', float32[0]
packed string: 'abcd' as two 16-bit integers: 25185 25699 as a single 32-bit integer 1684234849 as a 32-bit float 1.67779994081e+22
![[Packing a Variable-Length Vector]](./img/binary/pack_vec.png)
Figure 18.8: Packing a Variable-Length Vector
def pack_vec(vec):
buf = struct.pack('i', len(vec))
for v in vec:
buf += struct.pack('i', v)
return buf
def unpack_vec(buf):
# Get the count of the number of elements in the vector.
int_size = struct.calcsize('i')
count = struct.unpack('i', buf[0:int_size])[0]
# Get 'count' values, one by one.
pos = int_size
result = []
for i in range(count):
v = struct.unpack('i', buf[pos:pos+int_size])
result.append(v[0])
pos += int_size
return resultdef unpack_vec(buf):
# Get the count of the number of elements in the vector.
int_size = struct.calcsize('i')
count = struct.unpack('i', buf[0:int_size])[0]
# Get 'count' values, one by one.
pos = int_size
result = []
for i in range(count):
v = struct.unpack('i', buf[pos:pos+int_size])
result.append(v[0])
pos += int_size
return resultdef pack_strings(strings):
result = ''
for s in strings:
length = len(s)
format = 'i%ds' % length
result += struct.pack(format, length, s)
return result
def unpack_strings(buf):
int_size = struct.calcsize('i')
pos = 0
result = []
while pos < len(buf):
length = struct.unpack('i', buf[pos:pos+int_size])[0]
pos += int_size
format = '%ds' % length
s = struct.unpack(format, buf[pos:pos+length])[0]
pos += length
result.append(s)
return resultdef unpack_strings(buf):
int_size = struct.calcsize('i')
pos = 0
result = []
while pos < len(buf):
length = struct.unpack('i', buf[pos:pos+int_size])[0]
pos += int_size
format = '%ds' % length
s = struct.unpack(format, buf[pos:pos+length])[0]
pos += length
result.append(s)
return result![[Structure of a Binary File With Metadata]](./img/binary/metadata.png)
Figure 18.9: Structure of a Binary File With Metadata
def store(outf, format, values):
'''Store a list of lists, each of which has the same structure.'''
length = struct.pack('i', len(format))
outf.write(length)
outf.write(format)
for v in values:
temp = [format] + v
binary = struct.pack(*temp)
outf.write(binary)struct.pack is calledstruct.pack to itstoredef retrieve(inf):
'''Retrieve data from a self-describing file.'''
data = inf.read(struct.calcsize('i'))
format_length = struct.unpack('i', data)[0]
format = inf.read(format_length)
record_size = struct.calcsize(format)
result = []
while True:
data = inf.read(record_size)
if not data:
break
values = list(struct.unpack(format, data))
result.append(values)
return resultfrom cStringIO import StringIO
tests = [
['i', [[17]]],
['ii', [[17, 18]]],
['ii', [[17, 18], [19, 20], [21, 22]]],
['if', [[17, 18.0], [19, 20.0]]]
]
for (format, original) in tests:
storage = StringIO()
temp = store(storage, format, original)
storage.seek(0)
final = retrieve(storage)
assert original == final| prev | Copyright © 2005-06 Python Software Foundation. | next |