Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Recipe 18.11. Formatting Integers as Binary Strings


Credit: Antti Kaihola, Scott David Daniels, W.J. van der
Laan


Problem


You need to display non-negative
integers in binary formthat is, you need to turn them into
strings made up of the characters '0' and
'1'.


Solution


The best approach, assuming you must perform this task on several
numbers in the course of one run of your application, is to first
prepare an auxiliary table, for example, with an auxiliary function:

def _bytes_to_bits( ):
# prepare and return a list of the first 256 int as binary strings
# start with table of the right length, filled with place-holders
the_table = 256*[None]
# we'll repeatedly need to loop on [7, 6, ..., 1, 0], make it once
bits_per_byte = range(7, -1, -1)
for n in xrange(256):
# prepare the nth string: start with a list of 8 place-holders
bits = 8*[None]
for i in bits_per_byte:
# get the i-th bit as a string, shift n right for next bit
bits[i] = '01'[n&1]
n >>= 1
# join up the 8-character string of 0's and 1's into the table
the_table[n] = ''.join(bits)
return the_table
# rebind function's name to the table, function not needed any more
_bytes_to_bits = _bytes_to_bits( )

and then use the auxiliary table to make a fast conversion function
that works 8 bits at a time:

def binary(n):
# check precondition: only non-negative numbers supported
assert n>=0
# prepare the list of substrings 8 bits at a time
bits = [ ]
while n:
bits.append(_bytes_to_bit[n&255])
n >>= 8
# we need it left-to-right, thus the reverse
bits.reverse( )
# strip leading '0's, but ensure at least one is left!
return ''.join(bits).lstrip('0') or '0'

If you need to perform this task only a very small number of times in
the course of one run of your application, you might instead choose
to perform the conversion directly, bit by
bitit's easy, although somewhat slow. Just
use the same approach as binary, but 1 bit at a time
instead of 8 bits at a time:

def binary_slow(n):
assert n>=0
bits = [ ]
while n:
bits.append('01'[n&1])
n >>= 1
bits.reverse( )
return ''.join(bits) or '0'


Discussion


If you also need to display negative numbers, you can take two
different roads. Either do as the built-in functions
hex and oct and prepend a minus
sign to negative numbers:

def bin_with_sign(n):
if n<0: return '-'+binary(-n)
else: return binary(n)

or use two's complement
notation, but in that case you need to know how many bits fit in a
"word", because
that's how two's complement is
definedin terms of fixed-length words:

def bin_twos_complement(n, bits_per_word=16):
if n<0: n = (2<<bits_per_word) + n
return binary(n)

Function binary produces just as many binary digits
as each argument needs, avoiding leading '0's
(except the single zero digit needed to avoid displaying an empty
string when n is 0). If instead you need
to produce a fixed number of binary digits, you could ensure that at
string level, which is particularly easy with Python 2.4:

def bin_fixed(n, bits_per_word=16):
return bin_twos_complement(n, bits_per_word).rjust(bits_per_word, '0')

but is also quite feasible with Python 2.3 as well:

def bin_fixed_23(n, bits_per_word=16):
result = bin_twos_complement(n, bits_per_word)
return (('0'*bits_per_word)+result)[-bits_per_word:]

Alternatively, you could generalize some version of the auxiliary
_bytes_to_bits function used in the
"Solution", which is indeed
oriented to producing fixed-length results. However, using the
variable-length version, and a little string manipulation on top of
it for the occasional need for fixed-length results, should be
enough.


See Also


Library Reference and Python in a
Nutshell
docs for built-ins oct and
hex; Recipe 18.12 for displaying integers in
an arbitrary base.


/ 394