Velocity Reviews > binary representation of an integer

# binary representation of an integer

eliben
Guest
Posts: n/a

 06-24-2008
Hello,

I'm interested in converting integers to a binary representation,
string. I.e. a desired function would produce:

dec2bin(13) => "1101"

The other way is easily done in Python with the int() function.

Perl has a very efficient way to do dec2bin, because its pack/unpack
have a B format for binary representations, so it's done with:

sub dec2bin {
my \$str = unpack("B32", pack("N", shift));
\$str =~ s/^0+(?=\d)//; # otherwise you'll get leading zeros
return \$str;
}

Python's pack/unpack don't have the binary format for some reason, so
custom solutions have to be developed. One suggested in the ASPN
cookbook is:
http://aspn.activestate.com/ASPN/Coo.../Recipe/111286
However, it is very general and thus inefficient.

What would be the quickest way to do this ? I think that for dec2bin
conversion, using hex() and then looping with a hex->bin lookup table
would be probably much faster than the general baseconvert from the
recipe.

What do you think?

Maric Michaud
Guest
Posts: n/a

 06-24-2008
Le Tuesday 24 June 2008 10:03:58 eliben, vous avez écrit*:
> Hello,
>
> I'm interested in converting integers to a binary representation,
> string. I.e. a desired function would produce:
>
> dec2bin(13) => "1101"
>
> The other way is easily done in Python with the int() function.
>
> Perl has a very efficient way to do dec2bin, because its pack/unpack
> have a B format for binary representations, so it's done with:
>
> sub dec2bin {
> my \$str = unpack("B32", pack("N", shift));
> \$str =~ s/^0+(?=\d)//; # otherwise you'll get leading zeros
> return \$str;
> }
>
> Python's pack/unpack don't have the binary format for some reason,

Yes, but I think the %b format specifier has been added to p3k but will not in
python 2.x.

> so
> custom solutions have to be developed. One suggested in the ASPN
> cookbook is:
> http://aspn.activestate.com/ASPN/Coo.../Recipe/111286
> However, it is very general and thus inefficient.
>
> What would be the quickest way to do this ? I think that for dec2bin
> conversion, using hex() and then looping with a hex->bin lookup table
> would be probably much faster than the general baseconvert from the
> recipe.
>
> What do you think?

Something like that, less typing with octal conversion

>>>[8]: oct2bin =

{'0':'000', '1':'001', '2':'010', '3':'011', '4':'100', '5':'101', '6':'110', '7':'111'}

>>>[9]: ''.join(oct2bin[e] for e in "%o"%35).lstrip('0')

...[9]: '100011'

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 4 26 88 00 97
Mobile: +33 6 32 77 00 21

Mark Dickinson
Guest
Posts: n/a

 06-24-2008
On Jun 24, 9:03*am, eliben <(E-Mail Removed)> wrote:
> What would be the quickest way to do this ? I think that for dec2bin
> conversion, using hex() and then looping with a hex->bin lookup table
> would be probably much faster than the general baseconvert from the
> recipe.

I suspect you're right, but it would be easy to find out: just
code up the hex->bin method and use the timeit module to do some
timings. Don't forget to strip the trailing 'L' from hex(n) if n
is a long.

If you're prepared to wait for Python 2.6, or work with the beta
version, then the conversion is already there:

Macintosh-3:trunk dickinsm\$ ./python.exe
Python 2.6b1+ (trunk:64489, Jun 23 2008, 21:10:40)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
>>> bin(13)

'0b1101'

Interestingly, unlike hex and oct, bin doesn't add a trailing
'L' for longs:

>>> bin(13L)

'0b1101'

I wonder whether this is a bug...

Mark

cokofreedom@gmail.com
Guest
Posts: n/a

 06-24-2008
On Jun 24, 10:38 am, Mark Dickinson <(E-Mail Removed)> wrote:
> On Jun 24, 9:03 am, eliben <(E-Mail Removed)> wrote:
>
> > What would be the quickest way to do this ? I think that for dec2bin
> > conversion, using hex() and then looping with a hex->bin lookup table
> > would be probably much faster than the general baseconvert from the
> > recipe.

>
> I suspect you're right, but it would be easy to find out: just
> code up the hex->bin method and use the timeit module to do some
> timings. Don't forget to strip the trailing 'L' from hex(n) if n
> is a long.
>
> If you're prepared to wait for Python 2.6, or work with the beta
> version, then the conversion is already there:
>
> Macintosh-3:trunk dickinsm\$ ./python.exe
> Python 2.6b1+ (trunk:64489, Jun 23 2008, 21:10:40)
> [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
>
> '0b1101'
>
> Interestingly, unlike hex and oct, bin doesn't add a trailing
> 'L' for longs:
>
> >>> bin(13L)

>
> '0b1101'
>
> I wonder whether this is a bug...
>
> Mark

Strange in 2.6, but I know at least in 3.0 that all integers are C
Long's now, so the L is no longer required.

cokofreedom@gmail.com
Guest
Posts: n/a

 06-24-2008
And:

# return as a string
def itob_string(integer, count = :
return "".join(str((integer >> i) & 1) for i in range(count - 1,
-1, -1))

# return as an iterator (i.e [0, 0, 0, 0, 1, 0, 1, 0])
def itob_list(integer, count = :
return [(integer >> i) & 1 for i in range(count - 1, -1, -1)]

# return as a generator
def itob_generator(integer, count = :
return ((integer >> i) & 1 for i in range(count - 1, -1, -1))

bearophileHUGS@lycos.com
Guest
Posts: n/a

 06-24-2008
eliben:
> Python's pack/unpack don't have the binary format for some reason, so
> custom solutions have to be developed. One suggested in the ASPN
> cookbook is:http://aspn.activestate.com/ASPN/Coo.../Recipe/111286
> However, it is very general and thus inefficient.

Try mine, it may be fast enough for your purposes:
http://aspn.activestate.com/ASPN/Coo.../Recipe/440528

Bye,
bearophile

Terry Reedy
Guest
Posts: n/a

 06-24-2008

http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Jun 24, 10:38 am, Mark Dickinson <(E-Mail Removed)> wrote:

>> Interestingly, unlike hex and oct, bin doesn't add a trailing
>> 'L' for longs:
>>
>>>>> bin(13L)

>> '0b1101'
>>
>> I wonder whether this is a bug...

> Strange in 2.6, but I know at least in 3.0 that all integers are C
> Long's now, so the L is no longer required.

In current 2.x, the trailing L is no longer required for long integer
input; the lexer decides whether to make an int or long. Similarly,
ints are automatically converted to longs as needed instead of raising
overflow errors (as once happended). The trailing L on output would
have been removed already except for backward compatibility. But there
was no back-compatibility requirement for 0bxxxx strings.

In 3.0, all integers are class 'int'. The internal representation as
fixed or extended precision is entirely an internal implementation matter.