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]
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.
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.
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)?
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.
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.
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
:)
Or to put it really short:
:)
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.
Made more generic and pythonic still:
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:
I may as well throw in my version. I find it simpler without recursion:
Well, here is my version.
@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:
Now if num = 0, it never goes into while loop and returns new_num_string which is "".
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'.
Here is another solution:
Output:
def base(decimal ,base) : list = "0123456789ABCDEFGHIJKLMOPQRSTUVWXYZ" answer = "" while decimal != 0 : answer += list[decimal % base] decimal /= base return answer[::-1] print base(100,8)
here is a another solution:
output:
I have expanded on mukundan's function to implement fraction base conversion capabilities.
Yet shorter version: