The function produces an arbitrary radix string representation of integer numbers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # radix.py
"""
Defines str(number,radix) -- reverse function to int(str,radix) and long(str,radix)
number -- signed int or long,
radix -- 2 to 36
Usage:
import radix
str_repr = radix.str( number, radix )
print radix.str( 10, 16 ), radix.str( 1570137287, 36 ) # a python
"""
import string
def str( number, radix ):
"""str( number, radix ) -- reverse function to int(str,radix) and long(str,radix)"""
if not 2 <= radix <= 36:
raise ValueError, "radix must be in 2..36"
abc = string.digits + string.letters
result = ''
if number < 0:
number = -number
sign = '-'
else:
sign = ''
while True:
number, rdigit = divmod( number, radix )
result = abc[rdigit] + result
if number == 0:
return sign + result
# never here because number >= 0, radix > 0, we repeat (number /= radix)
if __name__ == '__main__':
src = 'qwertyuioplkjhgfdsazxcvbnm0987654321'
dst = 79495849566202193863718934176854772085778985434624775545L
num = int( src, 36 )
assert num == dst
res = str( num, 36 )
assert res == src
print "%s radix 36 is\n%d decimal" % (src, dst)
# EOF
|
I've discovered that a function returning an arbitrary radix string from a number is missing in the language. So I implemented it to restore the symmetry.
Moon aka Sun
Tags: text
--> Category: Algorithms. I'm sorry, it belongs rather to the Algorithms Category.
See also here: Numeric base converter that accepts arbitrary digits
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/111286
A few nits. Nicely written.
Here are a few nits to take it to industrial strength:
rename the function to base() or some such to avoid overwriting __builtin__.str()
only build abc once and do it outside the function
use ''.join() on a list instead of quadratic time string addition.
make divmod, abc, and result.append into locals for faster lookup in the loop.
import string abc = string.digits + string.letters
def base(number, radix): """base(number, radix) inverse function to int(str,radix) and long(str,radix) """
if not 2 <= radix <= 36: raise ValueError, "radix must be in 2..36"
result = [] addon = result.append if number < 0: number = -number addon('-') elif number == 0: addon('0')
_divmod, _abc = divmod, abc while number: number, rdigit = _divmod(number, radix) addon(_abc[rdigit])
result.reverse() return ''.join(result)
Minus sign should be at the beginning. The code directly above puts the minus sign at the end instead of the beginning.
Here's the version I ended up with, which also allows you to use whatever characters you like as the digits:
typo. string.letters should be string.uppercase (or string.lowercase).