Base conversion method or module

J

Jeff Wagner

Is there a Python module or method that can convert between numeric bases? Specifically, I need to
convert between Hex, Decimal and Binary such as 5Ah = 90d = 01011010b.

I searched many places but couldn't find a Python specific one.

Thanks, Jeff
 
F

Francis Avila

Jeff Wagner wrote in message said:
Is there a Python module or method that can convert between numeric bases? Specifically, I need to
convert between Hex, Decimal and Binary such as 5Ah = 90d = 01011010b.

I searched many places but couldn't find a Python specific one.

Thanks, Jeff

There was a Python cookbook recipe that did these kinds of conversions,
IIRC. Look around at http://aspn.activestate.com/ASPN/Cookbook/Python.
Numeric might do this sort of thing, too, but I don't know.

Python itself can get you pretty far; the problem is that it's a bit spotty
in making conversions communicable.

For example, int() and long() both accept a string with a base argument, so
you can convert just about any base (2 <= base <= 36) to a Python int or
long.

Python can also go the other way around, taking a number and converting to a
string representation of the bases you want. The problem? There's only a
function to do this for hex and oct, not for bin or any of the other bases
int can handle.

Ideally, there's be a do-it-all function that is the inverse of int(): take
a number and spit out a string representation in any base (2-36) you want.

But the binary case is pretty simple:

def bin(number):
"""bin(number) -> string

Return the binary representation of an integer or long integer.

"""
if number == 0: return '0b0'
binrep = []
while number >0:
binrep.append(number&1)
number >>= 1
binrep.reverse()
return '0b'+''.join(map(str,binrep))


Dealing with negative ints is an exercise for the reader....

Remember also that Python has hex and octal literals.
 
J

Jeff Wagner

Jeff Wagner wrote in message said:
Is there a Python module or method that can convert between numeric bases? Specifically, I need to
convert between Hex, Decimal and Binary such as 5Ah = 90d = 01011010b.

I searched many places but couldn't find a Python specific one.

Thanks, Jeff

There was a Python cookbook recipe that did these kinds of conversions,
IIRC. Look around at http://aspn.activestate.com/ASPN/Cookbook/Python.
Numeric might do this sort of thing, too, but I don't know.

Python itself can get you pretty far; the problem is that it's a bit spotty
in making conversions communicable.

For example, int() and long() both accept a string with a base argument, so
you can convert just about any base (2 <= base <= 36) to a Python int or
long.

Python can also go the other way around, taking a number and converting to a
string representation of the bases you want. The problem? There's only a
function to do this for hex and oct, not for bin or any of the other bases
int can handle.

Ideally, there's be a do-it-all function that is the inverse of int(): take
a number and spit out a string representation in any base (2-36) you want.

But the binary case is pretty simple:

def bin(number):
"""bin(number) -> string

Return the binary representation of an integer or long integer.

"""
if number == 0: return '0b0'
binrep = []
while number >0:
binrep.append(number&1)
number >>= 1
binrep.reverse()
return '0b'+''.join(map(str,binrep))


Dealing with negative ints is an exercise for the reader....

Remember also that Python has hex and octal literals.

Francis,

I found the Python cookbook recipe you were referring to. It is as follows:

The module name is BaseConvert.py .......

#!/usr/bin/env python

BASE2 = "01"
BASE10 = "0123456789"
BASE16 = "0123456789ABCDEF"
BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"

def convert(number,fromdigits,todigits):

if str(number)[0]=='-':
number = str(number)[1:]
neg=1
else:
neg=0

# make an integer out of the number
x=long(0)
for digit in str(number):
x = x*len(fromdigits) + fromdigits.index(digit)

# create the result in base 'len(todigits)'
res=""
while x>0:
digit = x % len(todigits)
res = todigits[digit] + res
x /= len(todigits)
if neg:
res = "-"+res

return res

I am getting an error when I import this module and call it.

#!/usr/bin/python

import BaseConvert
print BaseConvert.convert(90,BASE10,BASE2)

Name Error: name 'Base10' is not defined.

This probably has something to do with namespaces which was biting me a while ago. I thought that
since the 'Base' definitions were global to this module (BaseConvert.py) by being defined outside
the function (convert), that when I imported this module, they would be global, too.

From one of my books, it says, "An import statement creates a new namespace that contains all the
attributes of the module. To access an attribute in this namespace, use the name of the module
object as a prefix: import MyModule ... a = MyModule.f( )" which is what I thought I was
doing.

What am I still missing?

Thanks,
Jeff
 
F

Fredrik Lundh

Jeff said:
I found the Python cookbook recipe you were referring to. It is as follows:

(what's wrong with just posting an URL?)
I am getting an error when I import this module and call it.

#!/usr/bin/python

import BaseConvert
print BaseConvert.convert(90,BASE10,BASE2)

Name Error: name 'Base10' is not defined.

This probably has something to do with namespaces which was biting me
a while ago. I thought that since the 'Base' definitions were global to this
module (BaseConvert.py) by being defined outside the function (convert),
that when I imported this module, they would be global, too.

in Python, "global" means "belonging to a module", not "visible in all
modules in my entire program"
What am I still missing?

change the call to use BaseConvert.BASE10 and BaseConvert.BASE2

to learn more about local and global names, read this:

http://www.python.org/doc/current/ref/naming.html

</F>
 
J

John Roth

Jeff Wagner said:
I am getting an error when I import this module and call it.

#!/usr/bin/python

import BaseConvert
print BaseConvert.convert(90,BASE10,BASE2)

Name Error: name 'Base10' is not defined.

This probably has something to do with namespaces which was biting me a while ago. I thought that
since the 'Base' definitions were global to this module (BaseConvert.py) by being defined outside
the function (convert), that when I imported this module, they would be global, too.

From one of my books, it says, "An import statement creates a new
namespace that contains all the
attributes of the module. To access an attribute in this namespace, use the name of the module
object as a prefix: import MyModule ... a = MyModule.f( )" which is what I thought I was
doing.

What am I still missing?

print BaseConvert.convert(90, BaseConvert.BASE10, BaseConvert.BASE2)

John Roth
 
F

Francis Avila

Jeff Wagner wrote in message ...

Hey, I found another one which is the more general "inverse of int/long"
function I was pining for (and thus learning for the n-th time that one
should check the cookbook first before reinventing the wheel):

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/222109

For some reason it's in the "Text" category, and uses the term "radix,"
which is less common than "base".

Hettinger's version (found in the discussion below) is better.

Shouldn't something like this get into the builtins, so we can get rid of
hex/oct in Python3k?
 
M

Mensanator

Subject: Re: Base conversion method or module
From: "Francis Avila" (e-mail address removed)
Date: 12/7/2003 8:52 PM Central Standard Time
Message-id: <[email protected]>


Jeff Wagner wrote in message ...
Hey, I found another one which is the more general "inverse of int/long"
function I was pining for (and thus learning for the n-th time that one
should check the cookbook first before reinventing the wheel):

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/222109

These are nice, but they're very slow:

For i=2**177149 - 1

224.797000051 sec for baseconvert
202.733999968 sec for dec2bin (my routine)
137.735000014 sec for radix

Compare those to the .digits function that is part of GMPY

0.59399998188 sec

That can make quite a difference when you're running through a couple million
iterations.
 
J

Jeff Wagner

Jeff Wagner wrote in message ...
Hey, I found another one which is the more general "inverse of int/long"
function I was pining for (and thus learning for the n-th time that one
should check the cookbook first before reinventing the wheel):

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/222109

For some reason it's in the "Text" category, and uses the term "radix,"
which is less common than "base".

Hettinger's version (found in the discussion below) is better.

Shouldn't something like this get into the builtins, so we can get rid of
hex/oct in Python3k?

Thanks Francis, this is excellent! I think I just made a major breakthrough. It's all starting to
come together. I'm sure something will stump me again, though (and it's going to be Classes when I
get there ;)

Jeff
 
J

Jeff Wagner

Subject: Re: Base conversion method or module
From: "Francis Avila" (e-mail address removed)
Date: 12/7/2003 8:52 PM Central Standard Time
Message-id: <[email protected]>


Jeff Wagner wrote in message ...

These are nice, but they're very slow:

For i=2**177149 - 1

224.797000051 sec for baseconvert
202.733999968 sec for dec2bin (my routine)
137.735000014 sec for radix

Compare those to the .digits function that is part of GMPY

0.59399998188 sec

That can make quite a difference when you're running through a couple million
iterations.

So I decide to go and try out this GMPY and download the win32 binaries. It consists of two files,
gmpy.pyd and pysymbolicext.pyd ... what do I do with them, just copy them to the lib folder?

Then it says I need GMP-4.x so I get that, too. It's like nothing I've ever seen before. How can I
install that on my WinXP box?

Thanks, Jeff
 
T

Terry Reedy

Jeff Wagner said:
So I decide to go and try out this GMPY and download the win32 binaries. It consists of two files,
gmpy.pyd and pysymbolicext.pyd ... what do I do with them, just copy them
to the lib folder?

Specifically, Pythonx.y/Libs/site-packages (at least on my system)

should have site-packages dir near beginning.
Then it says I need GMP-4.x so I get that, too. It's like nothing I've ever seen before. How can I
install that on my WinXP box?

no idea. sorry. .so is unix version of .dll. try gmp site for windows
..dll binary

tjr
 
M

Mensanator

Subject: Re: Base conversion method or module
From: Jeff Wagner (e-mail address removed)
Date: 12/8/2003 1:01 AM Central Standard Time
Message-id: <[email protected]>



So I decide to go and try out this GMPY and download the win32 binaries. It
consists of two files,
gmpy.pyd and pysymbolicext.pyd ... what do I do with them, just copy them to
the lib folder?

Yes. Did you get the documentation files also? You'll want gmpydoc.txt as it
lists all the functions. Unfortunately, it's a Unix test file (no carraige
returns) making it useless for Windows Notepad unless you convert the line
feeds to carraige return/line feed.
Then it says I need GMP-4.x so I get that, too. It's like nothing I've ever
seen before. How can I
install that on my WinXP box?

You only need that if you are going to compile from the source files. The
Windows binaries are already compiled, so you shouldn't need to do that step.
 
J

Jeff Wagner

Yes. Did you get the documentation files also? You'll want gmpydoc.txt as it
lists all the functions. Unfortunately, it's a Unix test file (no carraige
returns) making it useless for Windows Notepad unless you convert the line
feeds to carraige return/line feed.

Ok, I got it, cleaned it up and read it. It's pretty good.
You only need that if you are going to compile from the source files. The
Windows binaries are already compiled, so you shouldn't need to do that step.

Ok, I must have misunderstood. I am trying something that doesn't seem to be working.

If I try to take 01011010 (5A) from binary to hex, here is what I get:'0x41208'

From binary to decimal doesn't work either.'266760'

If I go from decimal to hex, it works.'0x5a'

From decimal to binary seems to work ok.'1011010'

From hex to binary seems to work.'1011010'

I''m not sure why the binary to x doesn't seem to work.

Jeff
 
A

Andrew Bennetts

Ok, I must have misunderstood. I am trying something that doesn't seem to be working.

If I try to take 01011010 (5A) from binary to hex, here is what I get:
'266760'

In Python, integer literals beginning with '0' are in octal, just as how
literals beginning with '0x' are in hex, so 01011010 really is 266760:
266760

So it looks like gmpy is functioning correctly.

-Andrew.
 
J

Jeff Wagner

In Python, integer literals beginning with '0' are in octal, just as how
literals beginning with '0x' are in hex, so 01011010 really is 266760:

266760

So it looks like gmpy is functioning correctly.

-Andrew.

Ok, so I get rid of the leading 0 and here is what I get:
'1011010'

why? How do I tell gmpy that 1011010 is binary and I want it to convert to decimal or hex?

Jeff
 
A

Andrew Bennetts

Ok, so I get rid of the leading 0 and here is what I get:

'1011010'

why? How do I tell gmpy that 1011010 is binary and I want it to convert to decimal or hex?

You seem to be confusing the value of a number with its representation.

Python's 'int' type simply holds a value. It doesn't know the difference
between 90, 0x5A, and int('1011010', 2). They are all the same number, even
though they represented differently in source code.

So, what you *really* are trying to ask is: "How do I take a representation
of a number in binary (i.e. base 2), and convert it to a representation in
decimal or hex?"

The answer is to first convert your representation to a value -- python's
builtin int can convert string representation of numbers with any base from
2 to 36, e.g.:
90

(I wouldn't be surprised if gmpy also could do this, but I don't know gmpy)

Note that I am passing strings to int, not bare literals! If I wrote
"int(1011010, 2)", python would compile 1011010 as a number in base 10, and
pass that number to int instead of the string representation of the number
we really want.

Then you want to pass this value to gmpy.digits, e.g.

num = int('1011010', 2)
print gmpy.digits(num, 16)

-Andrew.
 
J

Jeff Wagner

You seem to be confusing the value of a number with its representation.

Python's 'int' type simply holds a value. It doesn't know the difference
between 90, 0x5A, and int('1011010', 2). They are all the same number, even
though they represented differently in source code.

So, what you *really* are trying to ask is: "How do I take a representation
of a number in binary (i.e. base 2), and convert it to a representation in
decimal or hex?"

The answer is to first convert your representation to a value -- python's
builtin int can convert string representation of numbers with any base from
2 to 36, e.g.:

90

(I wouldn't be surprised if gmpy also could do this, but I don't know gmpy)

Note that I am passing strings to int, not bare literals! If I wrote
"int(1011010, 2)", python would compile 1011010 as a number in base 10, and
pass that number to int instead of the string representation of the number
we really want.

Then you want to pass this value to gmpy.digits, e.g.

num = int('1011010', 2)
print gmpy.digits(num, 16)

-Andrew.

Thank you ... wow, so much to learn. You're right, I was confusing the value of a number with its
representation.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,172
Messages
2,570,934
Members
47,475
Latest member
ShannonGro

Latest Threads

Top