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

This function takes in any base-10 integer and returns the string representation of that number in its specified base-n form.

Up to base-36 is supported without special notation for symbolizing when a number is really in a single digit position. When that does occur, the number that takes up that single base is surrounded by parantheses.

[2004-06-30: Renamed function to base10toN to be more proper]

[2001-06-17: Changed comments to base-36 instead of base-35; thanks Klaus Alexander Seistrup]

[2001-06-17: Added for loop mechanism in Discussion for alternative way of creating num_rep dictionary; thanks Hamish Lawson for suggesting that possibility]

Python, 42 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``` ```def base10toN(num,n): """Change a to a base-n number. Up to base-36 is supported without special notation.""" num_rep={10:'a', 11:'b', 12:'c', 13:'d', 14:'e', 15:'f', 16:'g', 17:'h', 18:'i', 19:'j', 20:'k', 21:'l', 22:'m', 23:'n', 24:'o', 25:'p', 26:'q', 27:'r', 28:'s', 29:'t', 30:'u', 31:'v', 32:'w', 33:'x', 34:'y', 35:'z'} new_num_string='' current=num while current!=0: remainder=current%n if 36>remainder>9: remainder_string=num_rep[remainder] elif remainder>=36: remainder_string='('+str(remainder)+')' else: remainder_string=str(remainder) new_num_string=remainder_string+new_num_string current=current/n return new_num_string ```

The main use for this function is to be able to easily know what a number looks like in binary, octal, and hexidecimal; binary especially. It is very useful for when you are dealing with bitwise operations and you want to know what the actual bits for a number look like.

As suggested by Hamish Lawson, the num_rep dictionary could be done using a for loop if you prefer:

starting_num=10 num_rep={} for letter in string.lowercase: num_rep[starting_num]=letter starting_num+=1

I have chosen to leave it as-is since the above has a very slight performance hit from the for loop and the way I have it in the code is more verbose.

Klaus Alexander Seistrup 20 years, 5 months ago

Max is base-36. Just as 9 is the biggest number in base-10, z is the biggest number in base-36, not base-35.

Hamish Lawson 20 years, 5 months ago

Setting up num_rep more concisely? Couldn't the num_rep dictionary be more concisely set up using a for loop (assuming you want to stick to doing the conversion using dictionary lookup rather than computation)?

Martin v. LĂ¶wis 18 years, 10 months ago

Input is not decimal. The description of the algorithm is incorrect: it does not take a decimal number as input, but a Python integer object - whether this was created through a decimal literal, or through a hexadecimal one, or through some other expression is irrelevant.

Greg Jorgensen 17 years, 5 months ago

quite a few problems, and not a great implementation. This code fails in several ways:

• base = 1 causes infinite loop

• base = 0 causes divide by zero

• non-numerics passed for number or base cause exception

• incorrectly converts number 0 to "" for any base

The code is much longer than it should be. Using a dictionary for a sequentially-indexed list of letters is wasteful; even worse is the suggestion to populate the dictionary with a for loop. Making the distinction between digits in the 0..9 range and digits in the a..z range over-complicates the code. The digits needed for bases 2..36 are a constant string.

Here's a version that doesn't have these problems (though it may have other bugs). And I think it is more Pythonic.

``````def baseconvert(n, base):
"""convert positive decimal integer n to equivalent in another base (2-36)"""

digits = "0123456789abcdefghijklmnopqrstuvwxyz"

try:
n = int(n)
base = int(base)
except:
return ""

if n &lt; 0 or base &lt; 2 or base &gt; 36:
return ""

s = ""
while 1:
r = n % base
s = digits[r] + s
n = n / base
if n == 0:
break

return s
``````

It doesn't deal with base > 36 but it should be obvious how to extend the code to do it.

Greg Jorgensen

PDXperts LLC - Portland, Oregon USA

Aloysio Figueiredo 14 years, 2 months ago
``````def base10toN(num,n):
return ((num == 0) and  "0" ) or ( base10toN(num // n, n).strip("0") + "0123456789abcdefghijklmnopqrstuvwxyz"[:n][num % n])
``````

:)

Aloysio Figueiredo 14 years, 2 months ago

Or to put it really short:

``````def base10toN(num,n):
return ((num == 0) and  "0" ) or ( base10toN(num // n, n).strip("0") + "0123456789abcdefghijklmnopqrstuvwxyz"[:n][num % n])
``````

:)

Kip Bryan 13 years, 9 months ago

Aloysio's short, but fixed. Thanks Aloysio for the inspiring one-liner version. However it didn't work for numbers that end in zero, such as 4 in base 2, which should be 100 but it gives 10. Here's an adjusted one. Note that none of these are converting from "base 10" as integers are stored in binary, normally. This also omits the [:n] substring from the original.

``````def baseN(num,b):
return ((num == 0) and  "0" ) or ( baseN(num // b, b).lstrip("0") + "0123456789abcdefghijklmnopqrstuvwxyz"[num % b])
``````
trottier 12 years, 10 months ago

Made more generic and pythonic still:

``````def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
return ((num == 0) and  "0" ) or ( baseN(num // b, b).lstrip("0") + numerals[num % b])
``````
wanyewon 12 years, 3 months ago

The previous versions had a few bugs: They didn't pass the numerals to the recursion call so you could only use different numerals for small numbers. Crazy cases like negative numbers and base 1 caused infinite recursions. The readability was that of an ancient Egyptian scroll.

Here's my take on this:

``````def baseN(num, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
"""
Convert any int to base/radix 2-36 string. Special numerals can be used
to convert to any base or radix you need. This function is essentially
an inverse int(s, base).

For example:
>>> baseN(-13, 4)
'-31'
>>> baseN(91321, 2)
'10110010010111001'
>>> baseN(791321, 36)
'gyl5'
>>> baseN(91321, 2, 'ab')
'babbaabaababbbaab'
"""
if num == 0:
return "0"

if num < 0:
return '-' + baseN((-1) * num, base, numerals)

if not 2 <= base <= len(numerals):
raise ValueError('Base must be between 2-%d' % len(numerals))

left_digits = num // base
if left_digits == 0:
return numerals[num % base]
else:
return baseN(left_digits, base, numerals) + numerals[num % base]
``````
sebastianjb 11 years, 3 months ago

I may as well throw in my version. I find it simpler without recursion:

``````def str_base(num, base, numerals = '0123456789abcdefghijklmnopqrstuvwxyz'):
if base < 2 or base > len(numerals):
raise ValueError("str_base: base must be between 2 and %i" % len(numerals))

if num == 0:
return '0'

if num < 0:
sign = '-'
num = -num
else:
sign = ''

result = ''
while num:
result = numerals[num % (base)] + result
num //= base

return sign + result
``````
Shashwat Anand 10 years, 9 months ago

Well, here is my version.

``````def base10toN(num, base):
"""Change ``num'' to given base
Upto base 36 is supported."""

converted_string, modstring = "", ""
currentnum = num
if not 1 < base < 37:
raise ValueError("base must be between 2 and 36")
if not num:
return '0'
while currentnum:
mod = currentnum % base
currentnum = currentnum // base
converted_string = chr(48 + mod + 7*(mod > 10)) + converted_string
return converted_string
``````
Shashwat Anand 10 years, 9 months ago

@Brett: Your recipe is Wrong for one particular case. It fails for num = 0. The answer should be '0' and not a blank string. The issue is with:

``````new_num_string=''
current=num
while current!=0:
# Foobar
return new_num_string
``````

Now if num = 0, it never goes into while loop and returns new_num_string which is "".

Jonathan Hartley 10 years, 4 months ago

Hey. I've never really been to ActiveState before, so I might be tripping over cultural norms here, but why are people posting competing snippets of code without any test cases? Seems like anyone coming to this page has to evaluate every snippet in turn until they find one that actually works, rather than simply being able to see at a glance 'passes all the tests' or 'doesnt'.

Marko Kukovec 8 years, 2 months ago

Here is another solution:

``````'''
Created on 20. sep. 2013

@author: Kukovec
'''

def __DecimalToAnyBaseArrayRecur__(array, decimal, base):
array.append(decimal % base)
div = decimal / base
if(div == 0):
return;
__DecimalToAnyBaseArrayRecur__(array, div, base)

def DecimalToAnyBaseArray(decimal, base):
array = []
__DecimalToAnyBaseArrayRecur__(array, decimal, base)
return array[::-1]

def Test():
print DecimalToAnyBaseArray(1258, 16)
print DecimalToAnyBaseArray(1258, 10)
print DecimalToAnyBaseArray(1258, 8)
print DecimalToAnyBaseArray(1258, 2)

if __name__ == "__main__":
Test()
``````

Output:

``````[4, 14, 10]
[1, 2, 5, 8]
[2, 3, 5, 2]
[1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
``````
mukundan 7 years, 2 months ago

def base(decimal ,base) : list = "0123456789ABCDEFGHIJKLMOPQRSTUVWXYZ" answer = "" while decimal != 0 : answer += list[decimal % base] decimal /= base return answer[::-1] print base(100,8)

mukundan 7 years, 2 months ago

here is a another solution:

``````def base(decimal ,base) :
list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while decimal != 0 :
decimal /= base

print base(35,36)
``````

output:

``````Z
``````
Pier 6 years ago

I have expanded on mukundan's function to implement fraction base conversion capabilities.

``````def base(decimal,base) :
"""
expand mukundan's function adding capability to convert fractions,
from http://www.cut-the-knot.org/blue/frac_conv.shtml
"""
list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
int_dec=int(decimal)
frac_dec=decimal-int(decimal)
int_result = ""
frac_result = ""
while int_dec != 0 :
int_result  += list[int_dec % base]
int_dec /= base
while frac_dec != 0 :
frac_result += list[int(frac_dec*base)]
frac_dec = frac_dec*base - int(frac_dec*base)
return int_result[::-1] + "." + frac_result[::1]
``````
Tibor Tajti 4 years, 6 months ago

Yet shorter version:

``````def tobaseN(n,N,D="0123456789abcdefghijklmnopqrstuvwxyz"):
return (tobaseN(n//N,N)+D[n%N]).lstrip("0") if n>0 else "0"
``````
 Created by Brett Cannon on Thu, 14 Jun 2001 (PSF)

### Tags

• (none)
▶ Show machine tags (4)

### Required Modules

• (none specified)