Welcome, guest | Sign In | My Account | Store | Cart

The function produces an arbitrary radix string representation of integer numbers.

Python, 57 lines
 ``` 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

Moon aka Sun (author) 19 years, 6 months ago

--> Category: Algorithms. I'm sorry, it belongs rather to the Algorithms Category.

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

Raymond Hettinger 19 years, 6 months ago

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

• make divmod, abc, and result.append into locals for faster lookup in the loop.

import string abc = string.digits + string.letters

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)

Richard Nichols III 15 years, 5 months ago
``````added an optional minimim-width parameter.
note: '0' * -1 == ''

import string
abc = string.digits + string.letters

"""

if not 2 &lt;= radix &lt;= 36:
raise ValueError, "radix must be in 2..36"

result = []
if number &lt;
number = -number

_divmod, _abc = divmod, abc
while number:

result.reverse()
return ''.join(result)
``````
Damon McCormick 14 years, 9 months ago

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:

``````def toRadixStr (number, radix, width=1,
digits=string.digits+string.letters):
digitCount = len(digits)
if not 2 &lt;= radix &lt;= digitCount:
raise ValueError, "radix must be in 2..%d" % digitCount
result = []
# convert some globals to locals for speed
_divmod, _digits = divmod, digits
append = result.append
# check for a negative number
if number &lt; 0:
number = -number
isNegative = True
else:
isNegative = False
# append digits in reverse order
while number:
append(_digits[remainder])
leading0s = digits[0] * (width-len(result)) # note: "0" * -1 == ''
# append sign if necessary and reverse
if isNegative:
append('-')
result.reverse()
return ''.join(result)
``````
Damon McCormick 14 years, 9 months ago

typo. string.letters should be string.uppercase (or string.lowercase).

 Created by Moon aka Sun on Tue, 16 Sep 2003 (PSF)