Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python elegant inverse function of int(string,base)

Tags:

python

Python allows conversions from string to integer using any base in the range [2,36] using:

int(string,base)

I am looking for an elegant inverse function that takes an integer and a base and returns a string.

For example:

>>> str_base(224,15)
'ee'

I came up with the following solution:

def digit_to_char(digit):
    if digit < 10: return chr(ord('0') + digit)
    else: return chr(ord('a') + digit - 10)

def str_base(number,base):
    if number < 0:
        return '-' + str_base(-number,base)
    else:
        (d,m) = divmod(number,base)
        if d:
            return str_base(d,base) + digit_to_char(m)
        else:
            return digit_to_char(m)

Note: digit_to_char() works for bases <= 169 arbitrarily using ASCII characters after z as digits for bases above 36.

Is there a Python built‑in, library function, or a more elegant inverse function of int(string,base)?

like image 239
random guy Avatar asked Jan 14 '10 10:01

random guy


People also ask

How do you specify a base in Python?

Python - int()Second parameter to the function is the base of number system. Here �12' is string representation of octal number that is equivalent to 10 (Ten) in decimal number system (with base=10). Similarly, Hexadecimal number (with base=16) is converted to decimal number.

How do you convert a string representation of a number from one base to another base in Python?

There is a way to convert to different bases by dividing the base 10 number by the base and taking the remainder and repeating until it is not divisible and write the quotient followed by all the remainders. (EX. 50/6 = 8 R 2, 8/6 = 1 R2 so 50 in base 6 would be 122).

How do you change the base of an integer in Python?

In Python, you can simply use the bin() function to convert from a decimal value to its corresponding binary value. And similarly, the int() function to convert a binary to its decimal value. The int() function takes as second argument the base of the number to be converted, which is 2 in case of binary numbers.


4 Answers

Maybe this shouldn't be an answer, but it could be helpful for some: the built-in format function does convert numbers to string in a few bases:

>>> format(255, 'b') # base 2 '11111111' >>> format(255, 'd') # base 10 '255' >>> format(255, 'o') # base 8 '377' >>> format(255, 'x') # base 16 'ff' 
like image 101
etuardu Avatar answered Sep 18 '22 11:09

etuardu


If you use Numpy, there is numpy.base_repr.

You can read the code under numpy/core/numeric.py. Short and elegant

like image 44
Pierre-Luc Bacon Avatar answered Sep 19 '22 11:09

Pierre-Luc Bacon


This thread has some example implementations.

Actually I think your solution looks rather nice, it's even recursive which is somehow pleasing here.

I'd still simplify it to remove the else, but that's probably a personal style thing. I think if foo: return is very clear, and doesn't need an else after it to make it clear it's a separate branch.

def digit_to_char(digit):
    if digit < 10:
        return str(digit)
    return chr(ord('a') + digit - 10)

def str_base(number,base):
    if number < 0:
        return '-' + str_base(-number, base)
    (d, m) = divmod(number, base)
    if d > 0:
        return str_base(d, base) + digit_to_char(m)
    return digit_to_char(m)

I simplified the 0-9 case in digit_to_char(), I think str() is clearer than the chr(ord()) construct. To maximize the symmetry with the >= 10 case an ord() could be factored out, but I didn't bother since it would add a line and brevity felt better. :)

like image 43
unwind Avatar answered Sep 18 '22 11:09

unwind


The above answers are really nice. It helped me a lot to prototype an algortithm I had to implement in C

I'd like to come up with a little change (I used) to convert decimal to a base of symbolspace

I also ignored negativ values just for shortness and the fact that's mathematical incorrect --> other rules for modular arithmetics --> other math if you use binary, oct or hex --> diff in unsigned & signed values

def str_base(number, base):
   (d,m) = divmod(number,len(base))
   if d > 0:
      return str_base(d,base)+base[m]
   return base[m]

that lead's to following output

>>> str_base(13,'01')
'1101'
>>> str_base(255,'01')
'11111111'
>>> str_base(255,'01234567')
'377'
>>> str_base(255,'0123456789')
'255'
>>> str_base(255,'0123456789abcdef')
'ff'
>>> str_base(1399871903,'_helowrd')
'hello_world'

if you want to padd with the propper zero symbol you can use

symbol_space = 'abcdest'

>>> str_base(734,symbol_space).rjust(0,symbol_space[0])
'catt'
>>> str_base(734,symbol_space).rjust(6,symbol_space[0])
'aacatt'
like image 20
chris.stckhmr Avatar answered Sep 20 '22 11:09

chris.stckhmr