Come convertire un numero intero in una stringa in qualsiasi base?


203

Python consente di creare facilmente un numero intero da una stringa di una data base tramite

int(str, base). 

Voglio eseguire l'inverso: creazione di una stringa da un numero intero , cioè voglio una funzione int2base(num, base), tale che:

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

Il nome della funzione / l'ordine degli argomenti non è importante.

Per qualsiasi numero xe base bche int()accetteranno.

Questa è una funzione facile da scrivere: in effetti è più facile che descriverla in questa domanda. Tuttavia, mi sento come se mi mancasse qualcosa.

Conosco le funzioni bin, oct, hex, ma io non li posso usare per alcuni motivi:

  • Queste funzioni non sono disponibili nelle versioni precedenti di Python, con le quali ho bisogno di compatibilità con (2.2)

  • Voglio una soluzione generale che possa essere chiamata allo stesso modo per basi diverse

  • Voglio consentire basi diverse da 2, 8, 16

Relazionato


5
Sorprendentemente nessuno ha dato una soluzione che funziona con una grande base arbitraria (1023). Se ne hai bisogno, controlla la mia soluzione che funziona per ogni base (da 2 a inf) stackoverflow.com/a/28666223/1090562
Salvador Dali,

Risposte:


98

Se hai bisogno di compatibilità con le versioni antiche di Python, puoi usare gmpy (che include una funzione di conversione da int a stringa veloce e completamente generale, e può essere costruito per versioni così antiche - potrebbe essere necessario provare versioni precedenti dal quelli recenti non sono stati testati per le versioni venerabili di Python e GMP, ma solo di versioni un po 'recenti), o, per meno velocità ma più comodità, utilizzare il codice Python - ad esempio, più semplicemente:

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)

8
Solo nel caso (gmpy2) sembra che la funzione di cui parla Alex gmpy2.digits(x, base).
mlvljr,

2
Mi è stato segnalato che alcuni casi necessitano di una base> 36 e quindi dovrebbero essere gli scavidigs = string.digits + string.lowercase + string.uppercase
Paul

4
(o string.digits + string.letters)
kojiro,

3
Qualche idea sul perché convert-base-N-to-string non sia incluso di default in Python? (È in Javascript.) Sì, possiamo tutti scrivere la nostra implementazione, ma ho cercato su questo sito e altrove, e molti di loro hanno dei bug. Meglio avere una versione testata e affidabile inclusa nella distribuzione principale.
Jason S,

4
@ lordscales91 Puoi anche usare ciò x //= baseche si comporta come /=in Python 2 nel far cadere il decimale. Questa risposta dovrebbe includere un disclaimer che è per Python 2.
Noumenon

100

Sorprendentemente, le persone davano solo soluzioni che si convertivano in piccole basi (più piccole della lunghezza dell'alfabeto inglese). Non c'è stato alcun tentativo di fornire una soluzione che si converta in qualsiasi base arbitraria da 2 a infinito.

Quindi ecco una soluzione super semplice:

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

quindi se hai bisogno di convertire un numero enorme nella base 577,

numberToBase(67854 ** 15 - 102, 577), Vi darà una soluzione corretta: [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],

Che puoi convertire in seguito in qualsiasi base tu voglia


Al college ho inventato una funzione che ha formattato le basi inferiori a 20 in notazione standard e le basi 20 e oltre in "decimale delimitato da due punti". Ad esempio, ha int(4545,16)dato "11c1" e ha int(4545,60)dato "1:15:45". Quindi la funzione ha triplicato il compito: la conversione in formati decimali, informatici e timestamp.
Peter Raynham,

1
Qual è la funzione inversa per questo metodo?
Sohrab T,

Questo non risponde alla domanda posta per 3 motivi, 1: la domanda posta per una funzione di libreria esistente non è un'implementazione 2: la domanda ha richiesto una stringa, questo produce un elenco 3: questo non è un inverso per int (str, base) incorporato.
lavare il

@plugwash 1) ad un certo punto noterai che a volte non esiste una funzione di libreria integrata per fare le cose che vuoi, quindi devi scriverne una tua. Se non sei d'accordo, pubblica la tua soluzione con una funzione integrata che può convertire un numero base 10 in base 577. 2) ciò è dovuto alla mancanza di comprensione del significato di un numero in una base. 3) Ti incoraggio a pensare per un po 'perché la base nel tuo metodo funziona solo per n <= 36. Una volta terminato, sarà ovvio il motivo per cui la mia funzione restituisce un elenco e ha la firma che ha.
Salvador Dali,

1
Questo non funziona per i numeri negativi e non sono sicuro di come farlo funzionare senza cambiarlo sostanzialmente. Forse aggiungendo un bit di segno, 1 o -1, nella parte superiore di digits?
wjandrea,

89
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
    return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])

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

Si prega di essere consapevoli del fatto che ciò può portare a

RuntimeError: maximum recursion depth exceeded in cmp

per numeri molto grandi.


5
Elegante nella sua brevità. Sembra funzionare con Python 2.2.3 per numeri interi non negativi. Un numero negativo si ripete all'infinito.
Mark Borgerding,

+1 utile; risolto un problema quando i numeri non iniziavano con '0'
sehe

4
Ciò fallisce silenziosamente (a) quando base è> len(numerals), e (b) num % bè, per fortuna, < len(numerals). ad es. sebbene la numeralsstringa contenga solo 36 caratteri, baseN (60, 40) ritorna '1k'mentre baseN (79, 40) genera un IndexError. Entrambi dovrebbero generare un qualche tipo di errore. Il codice dovrebbe essere rivisto per generare un errore se not 2 <= base <= len(numerals).
Chris Johnson,

3
@osa, il mio punto è che il codice scritto non riesce in modo molto negativo (silenziosamente, dando una risposta fuorviante) e potrebbe essere risolto facilmente. Se stai dicendo che non ci sarebbe alcun errore se tu sapessi in anticipo, per certo, che bnon supererebbe len(numerals), beh, buona fortuna a te.
Chris Johnson,

1
L'uso del corto circuito qui sembra inutilmente confuso ... perché non usare semplicemente un'istruzione if ... la linea return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]è altrettanto breve.
Ian Hincks,

83
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144

46
Ma fa solo quelle tre basi?
Thomas Ahle,

3
Sì, sfortunatamente non puoi specificare int base personalizzata. Maggiori informazioni sono qui: docs.python.org/library/string.html#formatstrings
Rost

3
Non 0è necessario. Ecco la documentazione di Python 2: docs.python.org/2/library/string.html#format-string-syntax
Evgeni Sergeev

7
È possibile ottenere gli stessi risultati con hex(100)[2:], oct(100)[2:]e bin(100)[2:].
Sassan,

2
@EvgeniSergeev: non è necessario solo su 2.7 / 3.1 +. Su 2.6, è richiesta la posizione esplicita (o il nome).
ShadowRanger

21

Grandi risposte! Immagino che la risposta alla mia domanda fosse "no". Non mi mancava una soluzione ovvia. Ecco la funzione che userò che condensa le buone idee espresse nelle risposte.

  • consentire la mappatura dei caratteri fornita dal chiamante (consente la codifica base64)
  • controlla negativo e zero
  • mappa numeri complessi in tuple di stringhe


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


4
Come si converte l'output base64 della nostra funzione in un numero intero?
detly

17

Ricorsivo

Vorrei semplificare la risposta più votata a:

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

Con lo stesso consiglio per RuntimeError: maximum recursion depth exceeded in cmpnumeri interi molto grandi e numeri negativi. (Puoi usare sys.setrecursionlimit(new_limit))

Iterativo

Per evitare problemi di ricorsione :

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
    res = ""
    while s:
        res+=BS[s%b]
        s//= b
    return res[::-1] or "0"

2
Splendidamente refactored e senza biblioteca.
Giampaolo Ferradini,

return BS[0] if not nAllora la condizione di arresto non dovrebbe essere ? Nel caso in cui tu voglia usare cifre fantasiose, come faccio io :)
Arnaud P

@ArnaudP concordato. Questo funziona per me:return BS[n] if n < b else to_base(n // b) + BN[n % b]
Jens

15

Python non ha una funzione integrata per la stampa di un numero intero in una base arbitraria. Dovrai scriverne uno tuo se lo desideri.


13

Puoi usare baseconv.pydal mio progetto: https://github.com/semente/python-baseconv

Esempio di utilizzo:

>>> 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'

Ci sono alcuni convertitori bultin come ad esempio baseconv.base2, baseconv.base16e baseconv.base64.


12

>>> numpy.base_repr(10, base=3) '101'


Bella soluzione. Nel mio caso, stavo evitando intorpidimento clacper problemi di tempo di caricamento. Il precarico numpy più che triplica il tempo di esecuzione della semplice valutazione delle espressioni in clac: ad esempio, è clac 1+1 passato da circa 40ms a 140ms.
Mark Borgerding,

1
Si noti che numpy.base_repr()ha un limite di 36 come base. Altrimenti genera unValueError
sbdchd il

Che corrisponde alla limitazione della funzione "int" incorporata. Basi più grandi richiedono di decidere cosa fare quando le lettere
finiscono

4

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

Eccone un altro dallo stesso 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

base10toN non tiene conto del caso di num == 0.
Craeft il

3

Ho creato un pacchetto pip per questo.

Vi consiglio di usare il mio bases.py https://github.com/kamijoutouma/bases.py che è stato ispirato da 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

fare riferimento a https://github.com/kamijoutouma/bases.py#known-basesalphabets per quali basi sono utilizzabili

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


Funziona come un incantesimo per le basi note specificate .
Agi Hammerthief,

Questa è di gran lunga la risposta migliore! E grazie per l'imballaggio del pip!
ɹɐʎɯɐʞ

3
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)

produzione:

"1F"


other-baseè lo stesso di other - base, quindi dovresti usareother_base
mbomb007

Inoltre, questo non funziona correttamente se decimalè zero.
mbomb007,

1
>>> 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'

1

Una soluzione ricorsiva per chi è interessato. Naturalmente, questo non funzionerà con valori binari negativi. Dovresti implementare il complemento a due.

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

1
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()

spiegazione

In ogni base ogni numero è uguale a a1+a2*base**2+a3*base**3...La "missione" è trovare tutti gli a.

Per ogni N=1,2,3...il codice sta isolando il aN*base**N"mouduling" con b per b=base**(N+1) cui taglia tutte le a sono più grandi di N e taglia tutte le a che il loro seriale è più piccolo di N diminuendo ogni volta che la funzione viene chiamata dalla corrente aN*base**N.

Base% (base-1) == 1 quindi base ** p% (base-1) == 1 e quindi q * base ^ p% (base-1) == q con una sola eccezione quando q = base-1 che restituisce 0. Per risolvere il problema nel caso in cui restituisca 0, la funzione sta verificando se è 0 dall'inizio.


vantaggi

in questo esempio ci sono solo una moltiplicazione (anziché divisione) e alcuni moudulueses che richiedono relativamente piccole quantità di tempo.


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

print(str(round(num, 2)) + "^" + str(power))

per favore, aggiungi alcune brevi informazioni sul fatto che hai fatto un init speciale
Farhana,

Sebbene ciò possa rispondere alla domanda degli autori, manca alcune parole esplicative e / o collegamenti alla documentazione. Gli snippet di codice non elaborati non sono molto utili senza alcune frasi attorno a loro. Puoi anche trovare molto utile come scrivere una buona risposta . Modifica la tua risposta
hellow

1
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]   

In questa funzione puoi facilmente convertire qualsiasi numero decimale nella tua base preferita.
montaqami,

Non hai bisogno di commentare la tua risposta, puoi semplicemente modificarla per aggiungere spiegazioni.
Pochmurnik,

1

Ecco un esempio di come convertire un numero di qualsiasi base in un'altra 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!!!")

0
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)

0

Un altro breve (e più facile da capire imo):

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

E con un'adeguata gestione delle eccezioni:

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")

0

Un'altra soluzione, funziona con le basi da 2 a 10, necessita di modifiche per basi superiori:

def n2b(n, b):
    if n == 0:
        return 0
    d = []
    while n:
        d.append(int(n % b))
        n /= b
    return ''.join(map(str,d[::-1]))

Esempio:

n2b(10,2) => '10100'
int(n2b(10,2),2) => 10

0

Ecco una versione ricorsiva che gestisce numeri interi con segno e cifre personalizzate.

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]

0

Le stringhe non sono l'unica scelta per rappresentare i numeri: puoi utilizzare un elenco di numeri interi per rappresentare l'ordine di ogni cifra. Questi possono essere facilmente convertiti in una stringa.

Nessuna delle risposte rifiuta la base <2; e la maggior parte verrà eseguita molto lentamente o si arresterà in modo anomalo con overflow dello stack per numeri molto grandi (come 56789 ** 43210). Per evitare tali guasti, ridurre rapidamente in questo modo:

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è paragonabile a strnumeri grandi (circa 0,3 secondi sulla mia macchina), ma se si confronta conhex te si potrebbe essere sorpresi (circa ms sulla mia macchina, o 1000 volte più veloce). Il motivo è perché il numero intero grande è archiviato nella memoria nella base 256 (byte). Ogni byte può essere semplicemente convertito in una stringa esadecimale di due caratteri. Questo allineamento si verifica solo per basi che sono potenze di due, motivo per cui ci sono casi speciali per 2,8 e 16 (e base64, ascii, utf16, utf32).

Considera l'ultima cifra di una stringa decimale. Come si collega alla sequenza di byte che ne costituisce il numero intero? Facciamo etichettare i byte s[i]con s[0]essendo meno significativo (little endian). Quindi l'ultima cifra è sum([s[i]*(256**i) % 10 for i in range(n)]). Bene, succede che 256 ** i termina con un 6 per i> 0 (6 * 6 = 36) in modo che l'ultima cifra sia (s[0]*5 + sum(s)*6)%10. Da questo, puoi vedere che l'ultima cifra dipende dalla somma di tutti i byte. Questa proprietà non locale è ciò che rende più difficile la conversione in decimale.


0
def baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]

Per python3 il tuo codice esegue questa operazione: baseConverter (0, 26) -> '' baseConverter (1, 26) -> '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' '' '1on -> 1 baseConverter (3, 26) -> 3 baseConverter (5, 26) -> 5 baseConverter (26, 26) -> 10 baseConverter (32, 26) -> 16
Drachenfels

0

Bene, io personalmente uso questa funzione, scritta da 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

Ecco come puoi usarlo

print(to_base(7, base=2))

Produzione: "111"

print(to_base(23, base=3))

Produzione: "212"

Sentiti libero di suggerire miglioramenti nel mio codice.


0
def base_conversion(num, base):
    digits = []
    while num > 0:
        num, remainder = divmod(num, base)
        digits.append(remainder)
    return digits[::-1]

0

Questa è una vecchia domanda, ma ho pensato di condividere la mia opinione in quanto ritengo sia più semplice che le altre risposte (buono per basi da 2 a 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

-1

Non ho visto nessun convertitore di float qui. E mi mancava il raggruppamento per sempre tre cifre.

FARE:

-numeri nell'espressione scientifica (n.nnnnnn*10**(exp)- '10'èself.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string funzione.

base 1 -> numeri romani?

-repr di complesso con agles

Quindi ecco la mia soluzione:

DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"


# note that the order of the digits is reversed for digits before the point
NO_GROUPING = lambda g: g

concat = "".join
concat_backwards = lambda g: concat(e for e in reversed(list(g)))

def grouping(length = 3, char = '_'):
    def yieldor(digits):
        i = 0
        for d in digits:
            if i == length:
                yield char
                i = 0
            yield d
            i+=1

    return yieldor

class Converter:
    def __init__(self, baseDigits: (int, str), beforePoint = NO_GROUPING, afterPoint = NO_GROUPING, decimalPoint = '.', digitPrecision = 16, trimZeros = True):
        if isinstance(baseDigits, int):
            baseDigits = DIGITS[:baseDigits]
        self.baseDigits = baseDigits

        self.beforePoint = beforePoint
        self.afterPoint  = afterPoint

        self.decimalPoint = decimalPoint
        self.digitPrecision = digitPrecision
        self.trimZeros = trimZeros

    def to_string(self, number: (int, float, complex)) -> str:
        if isinstance(number, complex):
            if number.imag == 0:
                return self.to_string(number.real)
            if number.real == 0:
                return self.to_string(number.imag) + 'j'
            return "({}+{}j)".format(self.to_string(number.real), self.to_string (number.imag))
        if number < 0:
            return '-' + self.to_string(-number)
        digitCount = len(self.baseDigits)
        if isinstance(number, float):
            # round correctly
            precError=digitCount**-self.digitPrecision
            number+=0.5*precError
            if self.trimZeros:
                def yieldor(n):
                    p = precError
                    for i in range(self.digitPrecision):
                        if n <= p:
                            return
                        p *= digitCount
                        n *= digitCount
                        digit = int(n)
                        n -= digit
                        yield self.baseDigits[digit]
            else:
                def yieldor(n):
                    for i in range(self.digitPrecision):
                        n *= digitCount
                        digit = int(n)
                        n -= digit
                        yield self.baseDigits[digit]

            a = concat(self.afterPoint(yieldor(number%1)))

            return (
                self.to_string(int(number)) + (a and self.decimalPoint + a)
            )

        else: #is int
            if not number: return self.baseDigits[0]
            def yieldor(n):
                while n:
                    n, digit = divmod(n, digitCount)
                    yield self.baseDigits[digit]
            return concat_backwards(self.beforePoint(yieldor(number)))

# some tests:
if __name__ == "__main__":
    def conv_test(num, digits, *argv, **kwv):
        print(num, "->", digits if isinstance(digits, int) else "{} ({})".format(len(digits), digits), Converter(digits, *argv, **kwv).to_string(num))
    conv_test(True, "ft")
    conv_test(123, 12, grouping(2))
    conv_test(-0xf00d, 16)
    conv_test(1000, True<<True, grouping(4))
    conv_test(1_000_000, "0+-", beforePoint = grouping(2, '|'))
    conv_test(1.5, 10)
    conv_test(0.999999999, 10, digitPrecision = 8)
    conv_test(-0.1, 10)

    import math
    conv_test(math.pi, 10, afterPoint = grouping(5, ' '))
    conv_test(0.123456789, 10, digitPrecision = 6)

    grSpc = grouping(1, ' ')
    conv_test(math.e, ["off", "on"], grSpc, grSpc, " dot ", digitPrecision = 7)

    conv_test(1 + 1.5j, 10)

    conv_test(50j, 10)

    conv_test(10.01, '-<>')

    # and generate some brainfuck-code here:
    conv_test(1701**42, '+-<>,.][', digitPrecision = 32)

-2
def bn(x,b,ab="0123456789abcdefghijklmnopqrstuvwxyz..."
    a = ""
    while (x>0):
        x,r = divmod(x,n)
        a += ab[r]
    return a[::-1]

bn(2**100, 36)

produzione:

3ewfdnca0n6ld1ggvfgg

per convertire in qualsiasi base, anche l'inverso è facile.


Ha ottenuto NameError: global name 'n' is not defined. È divmod(x, n)dovrebbe essere divmod(x, b)?
wjandrea,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.