How to convert an integer to a string in any base?

Question:

Python allows easy creation of an integer from a string of a given base via

int(str, base). 

I want to perform the inverse: creation of a string from an integer,
i.e. I want some function int2base(num, base), such that:

int(int2base(x, b), b) == x

The function name/argument order is unimportant.

For any number x and base b that int() will accept.

This is an easy function to write: in fact it’s easier than describing it in this question. However, I feel like I must be missing something.

I know about the functions bin, oct, hex, but I cannot use them for a few reasons:

  • Those functions are not available on older versions of Python, with which I need compatibility with (2.2)

  • I want a general solution that can be called the same way for different bases

  • I want to allow bases other than 2, 8, 16

Related

Asked By: Mark Borgerding

||

Answers:

http://code.activestate.com/recipes/65212/

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

Here’s another one from the same link

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 < 0 or base < 2 or base > 36:
        return ""

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

    return s
Answered By: John La Rooy
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
    return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])

ref:
http://code.activestate.com/recipes/65212/

Please be aware that this may lead to

RuntimeError: maximum recursion depth exceeded in cmp

for very big integers.

Answered By: jellyfishtree

If you need compatibility with ancient versions of Python, you can either use gmpy (which does include a fast, completely general int-to-string conversion function, and can be built for such ancient versions – you may need to try older releases since the recent ones have not been tested for venerable Python and GMP releases, only somewhat recent ones), or, for less speed but more convenience, use Python code – e.g., for Python 2, most simply:

import string
digs = string.digits + string.ascii_letters


def int2base(x, base):
    if x < 0:
        sign = -1
    elif x == 0:
        return digs[0]
    else:
        sign = 1

    x *= sign
    digits = []

    while x:
        digits.append(digs[int(x % base)])
        x = int(x / base)

    if sign < 0:
        digits.append('-')

    digits.reverse()

    return ''.join(digits)

For Python 3, int(x / base) leads to incorrect results, and must be changed to x // base:

import string
digs = string.digits + string.ascii_letters


def int2base(x, base):
    if x < 0:
        sign = -1
    elif x == 0:
        return digs[0]
    else:
        sign = 1

    x *= sign
    digits = []

    while x:
        digits.append(digs[x % base])
        x = x // base

    if sign < 0:
        digits.append('-')

    digits.reverse()

    return ''.join(digits)
Answered By: Alex Martelli
>>> import string
>>> def int2base(integer, base):
        if not integer: return '0'
        sign = 1 if integer > 0 else -1
        alphanum = string.digits + string.ascii_lowercase
        nums = alphanum[:base]
        res = ''
        integer *= sign
        while integer:
                integer, mod = divmod(integer, base)
                res += nums[mod]
        return ('' if sign == 1 else '-') + res[::-1]


>>> int2base(-15645, 23)
'-16d5'
>>> int2base(213, 21)
'a3'
Answered By: SilentGhost

Great answers!
I guess the answer to my question was “no” I was not missing some obvious solution.
Here is the function I will use that condenses the good ideas expressed in the answers.

  • allow caller-supplied mapping of characters (allows base64 encode)
  • checks for negative and zero
  • maps complex numbers into tuples of strings


def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
    'convert an integer to its string representation in a given base'
    if b<2 or b>len(alphabet):
        if b==64: # assume base64 rather than raise error
            alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
        else:
            raise AssertionError("int2base base out of range")
    if isinstance(x,complex): # return a tuple
        return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) )
    if x<=0:
        if x==0:
            return alphabet[0]
        else:
            return  '-' + int2base(-x,b,alphabet)
    # else x is non-negative real
    rets=''
    while x>0:
        x,idx = divmod(x,b)
        rets = alphabet[idx] + rets
    return rets

Answered By: Mark Borgerding
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144
Answered By: Rost

You could use baseconv.py from my project: https://github.com/semente/python-baseconv

Sample usage:

>>> from baseconv import BaseConverter
>>> base20 = BaseConverter('0123456789abcdefghij')
>>> base20.encode(1234)
'31e'
>>> base20.decode('31e')
'1234'
>>> base20.encode(-1234)
'-31e'
>>> base20.decode('-31e')
'-1234'
>>> base11 = BaseConverter('0123456789-', sign='$')
>>> base11.encode('$1234')
'$-22'
>>> base11.decode('$-22')
'$1234'

There is some bultin converters as for example baseconv.base2, baseconv.base16 and baseconv.base64.

Answered By: semente
def base(decimal ,base) :
    list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    other_base = ""
    while decimal != 0 :
        other_base = list[decimal % base] + other_base
        decimal    = decimal / base
    if other_base == "":
        other_base = "0"
    return other_base

print base(31 ,16)

output:

"1F"

Answered By: mukundan

A recursive solution for those interested. Of course, this will not work with negative binary values. You would need to implement Two's Complement.

def generateBase36Alphabet():
    return ''.join([str(i) for i in range(10)]+[chr(i+65) for i in range(26)])

def generateAlphabet(base):
    return generateBase36Alphabet()[:base]

def intToStr(n, base, alphabet):
    def toStr(n, base, alphabet):
        return alphabet[n] if n < base else toStr(n//base,base,alphabet) + alphabet[n%base]
    return ('-' if n < 0 else '') + toStr(abs(n), base, alphabet)

print('{} -> {}'.format(-31, intToStr(-31, 16, generateAlphabet(16)))) # -31 -> -1F
Answered By: Mr. Polywhirl

Surprisingly, people were giving only solutions that convert to small bases (smaller than the length of the English alphabet). There was no attempt to give a solution which converts to any arbitrary base from 2 to infinity.

So here is a super simple solution:

def numberToBase(n, b):
    if n == 0:
        return [0]
    digits = []
    while n:
        digits.append(int(n % b))
        n //= b
    return digits[::-1]

so if you need to convert some super huge number to the base 577,

numberToBase(67854 ** 15 - 102, 577), will give you a correct solution:
[4, 473, 131, 96, 431, 285, 524, 486, 28, 23, 16, 82, 292, 538, 149, 25, 41, 483, 100, 517, 131, 28, 0, 435, 197, 264, 455],

Which you can later convert to any base you want

  1. at some point of time you will notice that sometimes there is no built-in library function to do things that you want, so you need to write your own. If you disagree, post you own solution with a built-in function which can convert a base 10 number to base 577.
  2. this is due to lack of understanding what a number in some base means.
  3. I encourage you to think for a little bit why base in your method works only for n <= 36. Once you are done, it will be obvious why my function returns a list and has the signature it has.
Answered By: Salvador Dali

I made a pip package for this.

I recommend you use my bases.py https://github.com/kamijoutouma/bases.py which was inspired by bases.js

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

refer to https://github.com/kamijoutouma/bases.py#known-basesalphabets
for what bases are usable

EDIT:
pip link https://pypi.python.org/pypi/bases.py/0.2.2

Answered By: Belldandu
def dec_to_radix(input, to_radix=2, power=None):
    if not isinstance(input, int):
        raise TypeError('Not an integer!')
    elif power is None:
        power = 1

    if input == 0:
        return 0
    else:
        remainder = input % to_radix**power
        digit = str(int(remainder/to_radix**(power-1)))
        return int(str(dec_to_radix(input-remainder, to_radix, power+1)) + digit)

def radix_to_dec(input, from_radix):
    if not isinstance(input, int):
        raise TypeError('Not an integer!')
    return sum(int(digit)*(from_radix**power) for power, digit in enumerate(str(input)[::-1]))

def radix_to_radix(input, from_radix=10, to_radix=2, power=None):
    dec = radix_to_dec(input, from_radix)
    return dec_to_radix(dec, to_radix, power)
Answered By: nameisnotphil
def baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]
Answered By: gjivanya

Another short one (and easier to understand imo):

def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
    return (int_to_str(n/b, b, symbols) if n >= b else "") + symbols[n%b]

And with proper exception handling:

def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
    try:
        return (int_to_str(n/b, b) if n >= b else "") + symbols[n%b]
    except IndexError:
        raise ValueError(
            "The symbols provided are not enough to represent this number in "
            "this base")
Answered By: Ariel
def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
    baseit = lambda a=a, b=base: (not a) and numerals[0]  or baseit(a-a%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)]
    return baseit()

explanation

In any base every number is equal to a1+a2*base**2+a3*base**3... The "mission" is to find all a 's.

For everyN=1,2,3... the code is isolating the aN*base**N by "mouduling" by b for b=base**(N+1) which slice all a 's bigger than N, and slicing all the a 's that their serial is smaller than N by decreasing a everytime the func is called by the current aN*base**N .

Base%(base-1)==1 therefor base**p%(base-1)==1 and therefor q*base^p%(base-1)==q with only one exception when q=base-1 which returns 0.
To fix that in case it returns 0 the func is checking is it 0 from the beggining.


advantages

in this sample theres only one multiplications (instead of division) and some moudulueses which relatively takes small amounts of time.

Answered By: Shu ba

Here is a recursive version that handles signed integers and custom digits.

import string

def base_convert(x, base, digits=None):
    """Convert integer `x` from base 10 to base `base` using `digits` characters as digits.
    If `digits` is omitted, it will use decimal digits + lowercase letters + uppercase letters.
    """
    digits = digits or (string.digits + string.ascii_letters)
    assert 2 <= base <= len(digits), "Unsupported base: {}".format(base)
    if x == 0:
        return digits[0]
    sign = '-' if x < 0 else ''
    x = abs(x)
    first_digits = base_convert(x // base, base, digits).lstrip(digits[0])
    return sign + first_digits + digits[x % base]
Answered By: Antoine Pinsard

Strings aren't the only choice for representing numbers: you can use a list of integers to represent the order of each digit. Those can easily be converted to a string.

None of the answers reject base < 2; and most will run very slowly or crash with stack overflows for very large numbers (such as 56789 ** 43210). To avoid such failures, reduce quickly like this:

def n_to_base(n, b):
    if b < 2: raise # invalid base
    if abs(n) < b: return [n]
    ret = [y for d in n_to_base(n, b*b) for y in divmod(d, b)]
    return ret[1:] if ret[0] == 0 else ret # remove leading zeros

def base_to_n(v, b):
    h = len(v) // 2
    if h == 0: return v[0]
    return base_to_n(v[:-h], b) * (b**h) + base_to_n(v[-h:], b)

assert ''.join(['0123456789'[x] for x in n_to_base(56789**43210,10)])==str(56789**43210)

Speedwise, n_to_base is comparable with str for large numbers (about 0.3s on my machine), but if you compare against hex you may be surprised (about 0.3ms on my machine, or 1000x faster). The reason is because the large integer is stored in memory in base 256 (bytes). Each byte can simply be converted to a two-character hex string. This alignment only happens for bases that are powers of two, which is why there are special cases for 2,8, and 16 (and base64, ascii, utf16, utf32).

Consider the last digit of a decimal string. How does it relate to the sequence of bytes that forms its integer? Let's label the bytes s[i] with s[0] being the least significant (little endian). Then the last digit is sum([s[i]*(256**i) % 10 for i in range(n)]). Well, it happens that 256**i ends with a 6 for i > 0 (6*6=36) so that last digit is (s[0]*5 + sum(s)*6)%10. From this, you can see that the last digit depends on the sum of all the bytes. This nonlocal property is what makes converting to decimal harder.

Answered By: colski
num = input("number")
power = 0
num = int(num)
while num > 10:
    num = num / 10
    power += 1

print(str(round(num, 2)) + "^" + str(power))
Answered By: Casey Howard

Recursive

I would simplify the most voted answer to:

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(n, b): 
    return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]

With the same advice for RuntimeError: maximum recursion depth exceeded in cmp on very large integers and negative numbers. (You could usesys.setrecursionlimit(new_limit))

Iterative

To avoid recursion problems:

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
    res = ""
    while s:
        res+=BS[s%b]
        s//= b
    return res[::-1] or "0"
Answered By: M.M
>>> numpy.base_repr(10, base=3)
'101'

Note that numpy.base_repr() has a limit of 36 as its base. Otherwise it throws a ValueError

Answered By: V. Ayrat
def base_changer(number,base):
    buff=97+abs(base-10)
    dic={};buff2='';buff3=10
    for i in range(97,buff+1):
        dic[buff3]=chr(i)
        buff3+=1   
    while(number>=base):
        mod=int(number%base)
        number=int(number//base)
        if (mod) in dic.keys():
            buff2+=dic[mod]
            continue
        buff2+=str(mod)
    if (number) in dic.keys():
        buff2+=dic[number]
    else:
        buff2+=str(number)

    return buff2[::-1]   
Answered By: montaqami

Well I personally use this function, written by me

import string

def to_base(value, base, digits=string.digits+string.ascii_letters):    # converts decimal to base n

    digits_slice = digits[0:base]

    temporary_var = value
    data = [temporary_var]

    while True:
        temporary_var = temporary_var // base
        data.append(temporary_var)
        if temporary_var < base:
            break

    result = ''
    for each_data in data:
        result += digits_slice[each_data % base]
    result = result[::-1]

    return result

This is how you can use it

print(to_base(7, base=2))

Output:
"111"

print(to_base(23, base=3))

Output:
"212"

Please feel free to suggest improvements in my code.

Answered By: Artaza Sameen

Here is an example of how to convert a number of any base to another base.

from collections import namedtuple

Test = namedtuple("Test", ["n", "from_base", "to_base", "expected"])


def convert(n: int, from_base: int, to_base: int) -> int:
    digits = []
    while n:
        (n, r) = divmod(n, to_base)
        digits.append(r)    
    return sum(from_base ** i * v for i, v in enumerate(digits))


if __name__ == "__main__":
    tests = [
        Test(32, 16, 10, 50),
        Test(32, 20, 10, 62),
        Test(1010, 2, 10, 10),
        Test(8, 10, 8, 10),
        Test(150, 100, 1000, 150),
        Test(1500, 100, 10, 1050000),
    ]

    for test in tests:
        result = convert(*test[:-1])
        assert result == test.expected, f"{test=}, {result=}"
    print("PASSED!!!")
Answered By: Vlad Bezden
def base_conversion(num, base):
    digits = []
    while num > 0:
        num, remainder = divmod(num, base)
        digits.append(remainder)
    return digits[::-1]
Answered By: hxuanhung

This is an old question but I thought i'd share my take on it as I feel it is somewhat simpler that other answers (good for bases from 2 to 36):

def intStr(n,base=10):
    if n < 0   : return "-" + intStr(-n,base)         # handle negatives
    if n < base: return chr([48,55][n>9] + n)         # 48 => "0"..., 65 => "A"...
    return intStr(n//base,base) + intStr(n%base,base) # recurse for multiple digits
Answered By: Alain T.

I know this is an old post, but I'm just leaving my solution here just in case.

def decimal_to_given_base(integer_to_convert, base):
     remainder = integer_to_convert // base
     digit = integer_to_convert % base
     if integer_to_convert == 0:
         return '0'
     elif remainder == 0:
         return str(digit)
     else:
         return decimal_to_given_base(remainder, base) + str(digit)
Answered By: PSN

I made my function to do this. Run well on windows 10, python 3.7.3.

def number_to_base(number, base, precision = 10):
    if number == 0:
        return [0]
    
    positive = number >= 0
    number = abs(number)
    
    ints = []  # store the integer bases
    floats = []  # store the floating bases

    float_point = number % 1
    number = int(number)
    while number:
        ints.append(int(number%base))
        number //= base
    ints.reverse()
    
    while float_point and precision:
        precision -= 1
        float_point *= base
        floats.append(int(float_point))
        float_point = float_point - int(float_point)

    return ints, floats, positive


def base_to_str(bases, string="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
    """bases is a two dimension list, where bases[0] contains a list of the integers,
    and bases[1] contains a list of the floating numbers, bases[2] is a boolean, that's
    true when it's a positive number
    """
    ints = []
    floats = []

    for i in bases[0]:
        ints.append(string[i])

    for i in bases[1]:
        floats.append(string[i])

    if len(bases[1]) > 0:
        return (["-", ""][bases[2]] + "".join(ints)) + "." + ("".join(floats))
    else:
        return (["-", ""][bases[2]] + "".join(ints))
    

    

Example:

>>> base_to_str(number_to_base(-6.252, 2))
'-110.0100000010'
Answered By: Hzzkygcs

Say we want to convert 14 to base 2. We repeatedly apply the division algorithm until the quotient is 0:

14 = 2 x 7

7 = 2 x 3 + 1

3 = 2 x 1 + 1

1 = 2 x 0 + 1

The binary representation is just the remainder read from bottom to top. This can be proved by expanding

14 = 2 x 7 = 2 x (2 x 3 + 1) = 2 x (2 x (2 x 1 + 1) + 1) = 2 x (2 x (2 x (2 x 0 + 1) + 1) + 1) = 2^3 + 2^2 + 2

The code is the implementation of the above algorithm.

def toBaseX(n, X):
strbin = ""
while n != 0:
    strbin += str(n % X)
    n = n // X
return strbin[::-1]
Answered By: Adola

This is my approach. At first converting the number then casting it to string.

    def to_base(n, base):
        if base == 10:
            return n
        
        result = 0
        counter = 0
        
        while n:
            r = n % base
            n //= base
            result += r * 10**counter
            counter+=1
        return str(result)
Answered By: princebillyGK

I have written this function which I use to encode in different bases. I also provided the way to shift the result by a value 'offset'. This is useful if you'd like to encode to bases above 64, but keeping displayable chars (like a base 95).

I also tried to avoid reversing the output 'list' and tried to minimize computing operations. The array of pow(base) is computed on demand and kept for additional calls to the function.

The output is a binary string

pows = {}

######################################################
def encode_base(value,
                base = 10,
                offset = 0) :

    """
    Encode value into a binary string, according to the desired base.

    Input :
        value : Any positive integer value
        offset : Shift the encoding (eg : Starting at chr(32))
        base : The base in which we'd like to encode the value

    Return : Binary string

    Example : with : offset = 32, base = 64

              100 -> !D
              200 -> #(
    """

    # Determine the number of loops
    try :
        pb = pows[base]

    except KeyError :
        pb = pows[base] = {n : base ** n for n in range(0, 8) if n < 2 ** 48 -1}

    for n in pb :
        if value < pb[n] :
            n -= 1
            break

    out = []
    while n + 1 :
        b = pb[n]
        out.append(chr(offset + value // b))
        n -= 1
        value %= b

    return ''.join(out).encode()
Answered By: dcexcal

This function converts any integer from any base to any base

def baseconvert(number, srcbase, destbase):
    if srcbase != 10:
        sum = 0
        for _ in range(len(str(number))):
            sum += int(str(number)[_]) * pow(srcbase, len(str(number)) - _ - 1)
        b10 = sum
        return baseconvert(b10, 10, destbase)
    end = ''
    q = number
    while(True):
        r = q % destbase
        q = q // destbase
        end = str(r) + end
        if(q<destbase):
            end = str(q) + end
            return int(end)
Answered By: MediumSpringGreen

The below provided Python code converts a Python integer to a string in arbitrary base ( from 2 up to infinity ) and works in both directions. So all the created strings can be converted back to Python integers by providing a string for N instead of an integer.
The code works only on positive numbers by intention (there is in my eyes some hassle about negative values and their bit representations I don't want to dig into). Just pick from this code what you need, want or like, or just have fun learning about available options. Much is there only for the purpose of documenting all the various available approaches ( e.g. the Oneliner seems not to be fast, even if promised to be ).

I like the by Salvador Dali proposed format for infinite large bases. A nice proposal which works optically well even for simple binary bit representations. Notice that the width=x padding parameter in case of infiniteBase=True formatted string applies to the digits and not to the whole number. It seems, that code handling infiniteBase digits format runs even a bit faster than the other options - another reason for using it?

I don't like the idea of using Unicode for extending the number of symbols available for digits, so don't look in the code below for it, because it's not there. Use the proposed infiniteBase format instead or store integers as bytes for compression purposes.

    def inumToStr( N, base=2, width=1, infiniteBase=False,
    useNumpy=False, useRecursion=False, useOneliner=False, 
    useGmpy=False, verbose=True):
    ''' Positive numbers only, but works in BOTH directions.
    For strings in infiniteBase notation set for bases <= 62 
    infiniteBase=True . Examples of use:
    inumToStr( 17,  2, 1, 1)             # [1,0,0,0,1]
    inumToStr( 17,  3, 5)                #       00122
    inumToStr(245, 16, 4)                #        00F5
    inumToStr(245, 36, 4,0,1)            #        006T
    inumToStr(245245245245,36,10,0,1)    #  0034NWOQBH
    inumToStr(245245245245,62)           #     4JhA3Th 
        245245245245 == int(gmpy2.mpz('4JhA3Th',62))
    inumToStr(245245245245,99,2) # [25,78, 5,23,70,44]
    ----------------------------------------------------
    inumToStr( '[1,0,0,0,1]',2, infiniteBase=True ) # 17 
    inumToStr( '[25,78, 5,23,70,44]', 99) # 245245245245
    inumToStr( '0034NWOQBH', 36 )         # 245245245245 
    inumToStr( '4JhA3Th'   , 62 )         # 245245245245
    ----------------------------------------------------
    --- Timings for N = 2**4096, base=36: 
                                      standard: 0.0023
                                      infinite: 0.0017
                                      numpy   : 0.1277
                                      recursio; 0.0022
                                      oneliner: 0.0146
                For N = 2**8192: 
                                      standard: 0.0075
                                      infinite: 0.0053
                                      numpy   : 0.1369
    max. recursion depth exceeded:    recursio/oneliner
    '''
    show = print
    if type(N) is str and ( infiniteBase is True or base > 62 ):
        lstN = eval(N)
        if verbose: show(' converting a non-standard infiniteBase bits string to Python integer')
        return sum( [ item*base**pow for pow, item in enumerate(lstN[::-1]) ] )
    if type(N) is str and base <= 36:
        if verbose: show('base <= 36. Returning Python int(N, base)')
        return int(N, base)
    if type(N) is str and base <= 62:
        if useGmpy: 
            if verbose: show(' base <= 62, useGmpy=True, returning int(gmpy2.mpz(N,base))')
            return int(gmpy2.mpz(N,base))
        else:
            if verbose: show(' base <= 62, useGmpy=False, self-calculating return value)')
            lstStrOfDigits="0123456789"+ 
                "abcdefghijklmnopqrstuvwxyz".upper() + 
                "abcdefghijklmnopqrstuvwxyz"
            dictCharToPow = {}
            for index, char in enumerate(lstStrOfDigits):
                dictCharToPow.update({char : index}) 
            return sum( dictCharToPow[item]*base**pow for pow, item in enumerate(N[::-1]) )
        #:if
    #:if        
        
    if useOneliner and base <= 36:  
        if verbose: show(' base <= 36, useOneliner=True, running the Oneliner code')
        d="0123456789abcdefghijklmnopqrstuvwxyz"
        baseit = lambda a=N, b=base: (not a) and d[0]  or 
        baseit(a-a%b,b*base)+d[a%b%(base-1) or (a%b) and (base-1)]
        return baseit().rjust(width, d[0])[1:]

    if useRecursion and base <= 36: 
        if verbose: show(' base <= 36, useRecursion=True, running recursion algorythm')
        BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        def to_base(n, b): 
            return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]
        return to_base(N, base).rjust(width,BS[0])
        
    if base > 62 or infiniteBase:
        if verbose: show(' base > 62 or infiniteBase=True, returning a non-standard digits string')
        # Allows arbitrary large base with 'width=...' 
        # applied to each digit (useful also for bits )
        N, digit = divmod(N, base)
        strN = str(digit).rjust(width, ' ')+']'
        while N:
            N, digit = divmod(N, base)
            strN = str(digit).rjust(width, ' ') + ',' + strN
        return '[' + strN
    #:if        
    
    if base == 2:
        if verbose: show(" base = 2, returning Python str(f'{N:0{width}b}')")
        return str(f'{N:0{width}b}')
    if base == 8:
        if verbose: show(" base = 8, returning Python str(f'{N:0{width}o}')")
        return str(f'{N:0{width}o}')
    if base == 16:
        if verbose: show(" base = 16, returning Python str(f'{N:0{width}X}')")
        return str(f'{N:0{width}X}')

    if base <= 36:
        if useNumpy: 
            if verbose: show(" base <= 36, useNumpy=True, returning np.base_repr(N, base)")
            import numpy as np
            strN = np.base_repr(N, base)
            return strN.rjust(width, '0') 
        else:
            if verbose: show(' base <= 36, useNumpy=False, self-calculating return value)')
            lstStrOfDigits="0123456789"+"abcdefghijklmnopqrstuvwxyz".upper()
            strN = lstStrOfDigits[N % base] # rightmost digit
            while N >= base:
                N //= base # consume already converted digit
                strN = lstStrOfDigits[N % base] + strN # add digits to the left
            #:while
            return strN.rjust(width, lstStrOfDigits[0])
        #:if
    #:if
    
    if base <= 62:
        if useGmpy: 
            if verbose: show(" base <= 62, useGmpy=True, returning gmpy2.digits(N, base)")
            import gmpy2
            strN = gmpy2.digits(N, base)
            return strN.rjust(width, '0') 
            # back to Python int from gmpy2.mpz with 
            #     int(gmpy2.mpz('4JhA3Th',62))
        else:
            if verbose: show(' base <= 62, useGmpy=False, self-calculating return value)')
            lstStrOfDigits= "0123456789" + 
                "abcdefghijklmnopqrstuvwxyz".upper() + 
                "abcdefghijklmnopqrstuvwxyz"
            strN = lstStrOfDigits[N % base] # rightmost digit
            while N >= base:
                N //= base # consume already converted digit
                strN = lstStrOfDigits[N % base] + strN # add digits to the left
            #:while
            return strN.rjust(width, lstStrOfDigits[0])
        #:if
    #:if    
#:def
Answered By: Claudio

I'm presenting a "unoptimized" solution for bases between 2 and 9:

  def to_base(N, base=2):
    N_in_base = ''
    while True:
        N_in_base = str(N % base) + N_in_base
        N //= base
        if N == 0:
            break
    return N_in_base

This solution does not require reversing the final result, but it's actually not optimized. Refer to this answer to see why: https://stackoverflow.com/a/37133870/7896998

Answered By: Hou

Simple base transformation

def int_to_str(x, b):
    s = ""
    while x:
        s = str(x % b) + s
        x //= b
    return s

Example of output with no 0 to base 9

s = ""
x = int(input())
while x:
    if x % 9 == 0:
        s = "9" + s
        x -= x % 10
        x = x // 9
    else:
        s = str(x % 9) + s
        x = x // 9

print(s)
Answered By: Akram BEN GHANEM

While the currently top answer is definitely an awesome solution, there remains more customization users might like.

Basencode adds some of these features, including conversions of floating point numbers, modifying digits (in the linked answer, only numbers can be used).

Here's a possible use case:

>>> from basencode import *
>>> n1 = Number(12345)
>> n1.repr_in_base(64) # convert to base 64
'30V'
>>> Number('30V', 64) # construct Integer from base 64
Integer(12345)
>>> n1.repr_in_base(8)
'30071'
>>> n1.repr_in_octal() # shortcuts
'30071'
>>> n1.repr_in_bin() # equivelant to `n1.repr_in_base(2)`
'11000000111001'
>>> n1.repr_in_base(2, digits=list('-+')) # override default digits: use `-` and `+` in place of `0` and `1`
'++------+++--+'
>>> n1.repr_in_base(33) # yet another base - all bases from 2 to 64 are supported from the start
'bb3'

How would you add any bases you want? Let me replicate the example of the currently most upvoted answer: the digits parameter allows you to override the default digits from base 2 to 64, and provide digits for any base higher than that. The mode parameter determines how the value of the representation will determine how (list or string) the answer will be returned.

>>> n2 = Number(67854 ** 15 - 102)
>>> n2.repr_in_base(577, digits=[str(i) for i in range(577)], mode="l")
['4', '473', '131', '96', '431', '285', '524', '486', '28', '23', '16', '82', '292', '538', '149', '25', '41', '483', '100', '517', '131', '28', '0', '435', '197', '264', '455']
>>> n2.repr_in_base(577, mode="l") # the program remembers the digits for base 577 now
['4', '473', '131', '96', '431', '285', '524', '486', '28', '23', '16', '82', '292', '538', '149', '25', '41', '483', '100', '517', '131', '28', '0', '435', '197', '264', '455']

Operations can be done: the Number class returns an instance of basencode.Integer if the provided number is an Integer, else it returns a basencode.Float

>>> n3 = Number(54321) # the Number class returns an instance of `basencode.Integer` if the provided number is an Integer, otherwise it returns a `basencode.Float`.
>>> n1 + n3
Integer(66666)
>>> n3 - n1
Integer(41976)
>>> n1 * n3
Integer(670592745)
>>> n3 // n1
Integer(4)
>>> n3 / n1 # a basencode.Float class allows conversion of floating point numbers
Float(4.400243013365735)
>>> (n3 / n1).repr_in_base(32)
'4.cpr56v6rnc4oitoblha2r11sus0dheqd4pgechfcjklo74b2bgom7j8ih86mipdvss0068sehi9f3791mdo4uotfujq66cf0jkgo'
>>> n4 = Number(0.5) # returns a basencode.Float
>>> n4.repr_in_bin() # binary version of 0.5
'0.1'

Disclaimer: this project is under active maintenance, and I'm a contributor.

Answered By: Safwan Samsudeen
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.