Python elegant inverse function of int(string,base)

后端 未结 11 850
谎友^
谎友^ 2020-11-28 06:01

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

int(string,base)

im looking for an elegant inver

相关标签:
11条回答
  • 2020-11-28 06:12

    Looks like this might be my time to shine. Believe it or not, the following is some ported and modified Scratch code I wrote nearly three years ago to see just how quickly I could convert from denary to hexadecimal.

    Simply put, it works by first taking an integer, base, and an optional accompanying string of numerals, then calculating each digit of the converted integer beginning with the least significant.

    def int2base(num, base, abc="0123456789abcdefghijklmnopqrstuvwxyz"):
      if num < 0:
        return '-' + int2base(-num, base, abc)
    
      else:
        output = abc[num % base] # rightmost digit
    
        while num >= base:
          num //= base # move to next digit to the left
          output = abc[num % base] + output # this digit
    
        return output
    

    On my own PC, this code was able to complete 10 million iterations using the input range, 0-9999, and base, 36, in consistently below 5 seconds. Using the same test, I have found this to be at least 4 seconds faster than any other answer so far.

    >>> timeit.timeit(lambda: [int2base(n, 36) for n in range(10000)], number=1000)
    4.883068453882515
    
    0 讨论(0)
  • 2020-11-28 06:13

    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'
    
    0 讨论(0)
  • 2020-11-28 06:13

    review this.

    def int2str(num, base=16, sbl=None):
        if not sbl:
            sbl = '0123456789abcdefghijklmnopqrstuvwxyz'
        if len(sbl) < 2:
            raise ValueError, 'size of symbols should be >= 2'
        if base < 2 or base > len(sbl):
            raise ValueError, 'base must be in range 2-%d' % (len(sbl))
    
        neg = False
        if num < 0:
            neg = True
            num = -num
    
        num, rem = divmod(num, base)
        ret = ''
        while num:
            ret = sbl[rem] + ret
            num, rem = divmod(num, base)
        ret = ('-' if neg else '') + sbl[rem] + ret
    
        return ret
    
    0 讨论(0)
  • 2020-11-28 06:13

    Here's my solution:

    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 every N=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 every time the function is called by the current aN*base**N.

    Base%(base-1)==1 therefore base**p%(base-1)==1 and therefore 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 function is checking is it 0 from the beginning.


    Advantages

    In this sample, there is only one multiplication (instead of division) and some instances of modulus which take relatively small amounts of time.

    0 讨论(0)
  • 2020-11-28 06:14

    digit_to_char could be implemented like this:

    def digit_to_char(digit):
        return (string.digits + string.lowercase)[digit]
    
    0 讨论(0)
  • 2020-11-28 06:21

    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'
    
    0 讨论(0)
提交回复
热议问题