Reading a multi-byte number

Jeff Epler jepler at unpythonic.net
Mon May 19 16:54:47 EDT 2003


> Quoth Batista, Facundo:
> >                 valor += ord(car) * (255 ^ exp)
> 
On Mon, May 19, 2003 at 02:30:28PM -0600, Steven Taschuk wrote:
> (Btw, shouldn't that be "255**exp"?)

No, it should probably involve 256. (Or <<8)

Try the "struct" module.  It will let you read multi-byte numbers, provided
that the length in bytes is 1, 2, 4 (or 8 on platforms with 'long long').

If you want to read different lengths, use of struct.unpack may still be
an advantage, because you could do up to 8 bytes at a time instead of 1.
Or it might be premature optimization.  Something like the following
(untested):

import struct
def unpack(bytestring):
        nbytes = len(bytestring)
        num_quads = nbytes / 8
        num_chars = nbytes % 8
	print num_quads, num_chars
        format = "<%dQ%dB" % (num_quads, num_chars)
        parts = struct.unpack(format, bytestring)
        v = 0l
        shift = 0
        for i in range(num_quads):
                v = v | (parts[i] * 1L << shift)
                shift = shift + 64
        for i in range(num_chars):
                v = v | (parts[num_quads + i] * 1L << shift)
                shift = shift + 8
        return v

Of course, if what you want is a way to write Python long numbers
relatively efficiently, you might want to use 'marshal' to do so.  Consider
a 1000-bit number:
>>> len(str(1l<<1000))
302
>>> len(pickle.dumps(1l<<1000))
306
>>> len(marshal.dumps(1l<<1000))
139
>>> 1000/8
125

so the overhead of marshal is quite small for large numbers (1/16 length +
a few extra bytes) and this also encodes the length of the number.

Jeff





More information about the Python-list mailing list