Comment convertir un entier en chaîne dans n'importe quelle base?

203

Python permet de créer facilement un entier à partir d'une chaîne d'une base donnée via

int(str, base). 

Je veux effectuer l'inverse: création d'une chaîne à partir d'un entier , c'est-à-dire que je veux une fonction int2base(num, base), telle que:

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

L'ordre du nom / argument de la fonction est sans importance.

Pour tout nombre xet base bqui int()accepteront.

C'est une fonction facile à écrire: en fait c'est plus facile que de la décrire dans cette question. Cependant, je sens que je dois manquer quelque chose.

Je sais que sur les fonctions bin, oct, hex, mais je ne peux pas les utiliser pour quelques raisons:

  • Ces fonctions ne sont pas disponibles sur les anciennes versions de Python, avec lesquelles j'ai besoin de compatibilité avec (2.2)

  • Je veux une solution générale qui peut être appelée de la même manière pour différentes bases

  • Je veux autoriser des bases autres que 2, 8, 16

en relation

Mark Borgerding
la source
5
Étonnamment, personne n'a donné de solution qui fonctionne avec une grande base arbitraire (1023). Si vous en avez besoin, consultez ma solution qui fonctionne pour chaque base (2 à inf) stackoverflow.com/a/28666223/1090562
Salvador Dali

Réponses:

98

Si vous avez besoin de compatibilité avec les anciennes versions de Python, vous pouvez soit utiliser gmpy (qui inclut une fonction de conversion int-to-string rapide et complètement générale, et peut être construit pour ces anciennes versions - vous devrez peut-être essayer des versions plus anciennes depuis les versions récentes n'ont pas été testées pour les versions vénérables de Python et GMP, seulement des versions quelque peu récentes), ou, pour moins de vitesse mais pour plus de commodité, utiliser du code Python - par exemple, le plus simplement:

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)
Alex Martelli
la source
8
Juste dans le cas (gmpy2), la fonction dont parle Alex semble l'être gmpy2.digits(x, base).
mlvljr
2
Il a été porté à mon attention que certains cas ont besoin d'une base> 36 et donc les fouilles devraient êtredigs = string.digits + string.lowercase + string.uppercase
Paul
4
(ou string.digits + string.letters)
kojiro
3
Une idée pourquoi le convert-base-N-to-string n'est pas inclus par défaut dans Python? (C'est en Javascript.) Oui, nous pouvons tous écrire notre propre implémentation, mais j'ai cherché sur ce site et ailleurs, et beaucoup d'entre eux ont des bugs. Mieux vaut avoir une version testée et réputée incluse dans la distribution principale.
Jason S
4
@ lordscales91 Vous pouvez également utiliser x //= basece qui se comporte comme /=dans Python 2 en supprimant la décimale. Cette réponse devrait inclure un avertissement que c'est pour Python 2.
Noumenon
100

Étonnamment, les gens ne donnaient que des solutions qui se convertissaient en petites bases (plus petites que la longueur de l'alphabet anglais). Il n'y avait aucune tentative de donner une solution qui se transforme en n'importe quelle base arbitraire de 2 à l'infini.

Voici donc une solution super simple:

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

donc si vous avez besoin de convertir un très grand nombre en base 577,

numberToBase(67854 ** 15 - 102, 577), Vous donnera une bonne 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],

Que vous pourrez ensuite convertir en n'importe quelle base de votre choix

Salvador Dali
la source
Au collège, j'ai trouvé une fonction qui formatait les bases inférieures à 20 en notation standard, et les bases 20 et plus en «décimales délimitées par deux points». Par exemple, a int(4545,16)donné "11c1" et a int(4545,60)donné "1:15:45". Ainsi, la fonction remplit trois fonctions: la conversion aux formats décimal, informatique et d'horodatage.
Peter Raynham
1
Quelle est la fonction inverse de cette méthode?
Sohrab T
Cela ne répond pas à la question posée pour 3 raisons, 1: la question posée pour une fonction de bibliothèque existante pas une implémentation 2: la question posée pour une chaîne, cela produit une liste 3: ce n'est pas un inverse pour l'int (str, base) intégré.
plugwash
@plugwash 1) à un moment donné, vous remarquerez que parfois il n'y a pas de fonction de bibliothèque intégrée pour faire les choses que vous voulez, vous devez donc écrire la vôtre. Si vous n'êtes pas d'accord, publiez votre propre solution avec une fonction intégrée qui peut convertir un nombre de base 10 en base 577. 2) cela est dû au manque de compréhension de ce que signifie un nombre dans une base. 3) Je vous encourage à réfléchir un peu pourquoi la base de votre méthode ne fonctionne que pour n <= 36. Une fois que vous avez terminé, il sera évident que ma fonction retourne une liste et a la signature qu'elle a.
Salvador Dali
1
Cela ne fonctionne pas pour les nombres négatifs, et je ne sais pas comment le faire fonctionner sans le changer fondamentalement. Peut-être en ajoutant un bit de signe, 1 ou -1, en haut de 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])

réf: http://code.activestate.com/recipes/65212/

Veuillez noter que cela peut entraîner

RuntimeError: maximum recursion depth exceeded in cmp

pour les très grands entiers.

méduse
la source
5
Élégant dans sa brièveté. Il semble fonctionner sous python 2.2.3 pour les entiers non négatifs. Un nombre négatif revient indéfiniment.
Mark Borgerding du
+1 utile; correction d'un problème lorsque les chiffres ne commençaient pas par '0'
sehe
4
Cela échoue silencieusement (a) lorsque la base est> len(numerals), et (b) num % best, par chance, < len(numerals). Par exemple, bien que la numeralschaîne ne comporte que 36 caractères, baseN (60, 40) renvoie '1k'tandis que baseN (79, 40) lève un IndexError. Les deux devraient soulever une sorte d'erreur. Le code doit être révisé pour générer une erreur si not 2 <= base <= len(numerals).
Chris Johnson
3
@osa, mon point est que le code tel qu'il est écrit échoue de manière très mauvaise (en silence, donnant une réponse trompeuse) et pourrait être corrigé facilement. Si vous dites qu'il n'y aurait pas d'erreur si vous saviez à l'avance, bcela ne dépasserait certainement pas len(numerals), eh bien, bonne chance à vous.
Chris Johnson
1
L'utilisation de court-circuit semble ici inutilement déroutante ... pourquoi ne pas simplement utiliser une instruction if ... la ligne return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]est tout aussi brève.
Ian Hincks
83
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144
Rost
la source
46
Mais il ne fait que ces trois bases?
Thomas Ahle
3
Oui, malheureusement, vous ne pouvez pas spécifier de base int personnalisée. Plus d'informations sont ici: docs.python.org/library/string.html#formatstrings
Rost
3
C'est 0inutile. Voici la documentation de Python 2: docs.python.org/2/library/string.html#format-string-syntax
Evgeni Sergeev
7
Vous pouvez obtenir les mêmes résultats avec hex(100)[2:], oct(100)[2:]et bin(100)[2:].
Sassan
2
@EvgeniSergeev: C'est seulement inutile sur 2.7 / 3.1 +. Sur 2.6, la position explicite (ou le nom) est requise.
ShadowRanger
21

Excellentes réponses! Je suppose que la réponse à ma question était "non". Je ne manquais pas de solution évidente. Voici la fonction que j'utiliserai qui condense les bonnes idées exprimées dans les réponses.

  • autoriser le mappage des caractères fourni par l'appelant (autorise le codage base64)
  • vérifie le négatif et le zéro
  • mappe des nombres complexes en tuples de chaînes


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

Mark Borgerding
la source
4
Comment reconvertissez-vous la sortie base64 de notre fonction en un entier?
Detly
18

Récursif

Je simplifierais la réponse la plus votée à:

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

Avec le même conseil pour RuntimeError: maximum recursion depth exceeded in cmples très grands nombres entiers et les nombres négatifs. (Vous pourriez utiliser sys.setrecursionlimit(new_limit))

Itératif

Pour éviter les problèmes de récursivité :

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
    res = ""
    while s:
        res+=BS[s%b]
        s//= b
    return res[::-1] or "0"
MM
la source
2
Magnifiquement refactorisé et sans bibliothèque.
Giampaolo Ferradini
La condition d'arrêt ne devrait-elle pas être return BS[0] if not nalors? Juste au cas où vous voudriez utiliser des chiffres fantaisistes, comme moi :)
Arnaud P
@ArnaudP a accepté. Celui-ci fonctionne pour moi:return BS[n] if n < b else to_base(n // b) + BN[n % b]
Jens
15

Python n'a pas de fonction intégrée pour imprimer un entier dans une base arbitraire. Vous devrez écrire le vôtre si vous le souhaitez.

Mike Graham
la source
13

Vous pouvez utiliser à baseconv.pypartir de mon projet: https://github.com/semente/python-baseconv

Exemple d'utilisation:

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

Il existe des convertisseurs bultin comme par exemple baseconv.base2, baseconv.base16et baseconv.base64.

semente
la source
12

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

V. Ayrat
la source
Belle solution. Dans mon cas, j'évitais d'engourdir clacpour des soucis de temps de chargement. Le préchargement de numpy fait plus que tripler le temps d'exécution de l'évaluation d'une expression simple dans clac: par exemple, il clac 1+1 est passé d'environ 40 ms à 140 ms.
Mark Borgerding
1
Notez qu'il numpy.base_repr()a une limite de 36 comme base. Sinon, il jette unValueError
sbdchd
Ce qui correspond à la limitation de la fonction "int" intégrée. Les bases plus grandes nécessitent de décider quoi faire lorsque les lettres s'épuisent,
plugwash
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

Voici un autre à partir du même lien

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
John La Rooy
la source
base10toN ne tient pas compte du cas de num == 0.
Craeft
3

J'ai fait un paquet pip pour ça.

Je vous recommande d'utiliser mon bases.py https://github.com/kamijoutouma/bases.py qui a été inspiré par 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

reportez-vous à https://github.com/kamijoutouma/bases.py#known-basesalphabets pour connaître les bases utilisables

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

Belldandu
la source
Cela fonctionne comme un charme pour les bases connues spécifiées .
Agi Hammerthief
C'est de loin la meilleure réponse! Et merci pour l'emballage 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)

production:

"1F"

mukundan
la source
other-baseest le même que other - base, vous devez donc utiliserother_base
mbomb007
En outre, cela ne fonctionne pas correctement si decimalest égal à zéro.
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'
SilentGhost
la source
1

Une solution récursive pour les personnes intéressées. Bien sûr, cela ne fonctionnera pas avec des valeurs binaires négatives. Vous devez implémenter 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
M. Polywhirl
la source
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()

explication

Dans n'importe quelle base, chaque nombre est égal à a1+a2*base**2+a3*base**3...La «mission» est de trouver tous les a.

Pour tout N=1,2,3...le code isole le aN*base**Npar «mouduling» par b pour b=base**(N+1) lequel tranche tous les a plus gros que N, et tranche tous les a que leur série est plus petite que N en diminuant a chaque fois que la fonction est appelée par le courant aN*base**N.

Base% (base-1) == 1 à cet effet base ** p% (base-1) == 1 et donc q * base ^ p% (base-1) == q avec une seule exception lorsque q = base-1 qui renvoie 0. Pour corriger cela au cas où il retourne 0, le func vérifie qu'il est 0 depuis le début.


avantages

dans cet échantillon, il n'y a qu'une seule multiplication (au lieu de la division) et quelques moudulues qui prennent relativement peu de temps.

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

print(str(round(num, 2)) + "^" + str(power))
Casey Howard
la source
veuillez ajouter quelques brèves informations sur ce que vous avez fait init spécial
Farhana
Bien que cela puisse répondre à la question des auteurs, il manque des mots explicatifs et / ou des liens vers la documentation. Les extraits de code brut ne sont pas très utiles sans quelques phrases autour d'eux. Vous pouvez également trouver comment rédiger une bonne réponse très utile. Veuillez modifier votre réponse.
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]   
montaqami
la source
Dans cette fonction, vous pouvez facilement convertir n'importe quel nombre décimal en votre base préférée.
montaqami le
Vous n'avez pas besoin de commenter votre propre réponse, vous pouvez simplement la modifier pour ajouter des explications.
Pochmurnik
1

Voici un exemple de conversion d'un certain nombre de bases en une autre 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!!!")
Vlad Bezden
la source
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)
nameisnotphil
la source
0

Un autre court (et plus facile à comprendre imo):

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

Et avec une gestion des exceptions appropriée:

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")
Ariel
la source
0

Une autre solution, fonctionne avec la base 2 à 10, doit être modifiée pour les bases supérieures:

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

Exemple:

n2b(10,2) => '10100'
int(n2b(10,2),2) => 10
Stanislav
la source
0

Voici une version récursive qui gère les entiers signés et les chiffres personnalisés.

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]
Antoine Pinsard
la source
0

Les chaînes ne sont pas le seul choix pour représenter les nombres: vous pouvez utiliser une liste d'entiers pour représenter l'ordre de chaque chiffre. Ceux-ci peuvent facilement être convertis en chaîne.

Aucune des réponses ne rejette la base <2; et la plupart s'exécuteront très lentement ou planteront avec des débordements de pile pour de très grands nombres (comme 56789 ** 43210). Pour éviter de tels échecs, réduisez rapidement comme ceci:

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_baseest comparable à strpour les grands nombres (environ 0,3 s sur ma machine), mais si vous comparez contre hexvous pourriez être surpris (environ 0,3 ms sur ma machine, ou 1000 fois plus rapide). La raison en est que le grand entier est stocké en mémoire dans la base 256 (octets). Chaque octet peut simplement être converti en une chaîne hexadécimale à deux caractères. Cet alignement ne se produit que pour les bases qui sont des puissances de deux, c'est pourquoi il existe des cas spéciaux pour 2,8 et 16 (et base64, ascii, utf16, utf32).

Considérez le dernier chiffre d'une chaîne décimale. Comment est-il lié à la séquence d'octets qui forme son entier? Étiquetons les octets s[i]comme s[0]étant les moins significatifs (petit endian). Ensuite, le dernier chiffre est sum([s[i]*(256**i) % 10 for i in range(n)]). Eh bien, il arrive que 256 ** i se termine par un 6 pour i> 0 (6 * 6 = 36) de sorte que le dernier chiffre soit (s[0]*5 + sum(s)*6)%10. De là, vous pouvez voir que le dernier chiffre dépend de la somme de tous les octets. Cette propriété non locale rend la conversion en décimales plus difficile.

colski
la source
0
def baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]
gjivanya
la source
Pour python3, votre code fait ceci: baseConverter (0, 26) -> '' baseConverter (1, 26) -> '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' Pour python2 il fait ceci: baseConverter (0, 26) -> '' baseConverter (1, 26) -> 1 baseConverter (3, 26) -> 3 baseConverter (5, 26) -> 5 baseConverter (26, 26) -> 10 baseConverter (32, 26) -> 16
Drachenfels
0

Eh bien, j'utilise personnellement cette fonction, écrite par moi

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

Voilà comment vous pouvez l'utiliser

print(to_base(7, base=2))

Production: "111"

print(to_base(23, base=3))

Production: "212"

N'hésitez pas à suggérer des améliorations à mon code.

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

C'est une vieille question mais j'ai pensé partager mon point de vue car je pense que c'est un peu plus simple que les autres réponses (bon pour les bases de 2 à 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
Alain T.
la source
-1

Je n'ai vu aucun convertisseur de flotteur ici. Et j'ai raté le regroupement pour toujours trois chiffres.

FAIRE:

-Nombre expression scientifique (n.nnnnnn*10**(exp)- l' '10'estself.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-de-fonction-chaîne.

-base 1 -> nombres romains?

-repr de complexe avec agles

Voici donc ma solution:

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)
cmdLP
la source
-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)

production:

3ewfdnca0n6ld1ggvfgg

pour convertir en n'importe quelle base, l'inverse est aussi facile.

Rogério Duarte
la source
J'ai compris NameError: global name 'n' is not defined. Est divmod(x, n)censé l'être divmod(x, b)?
wjandrea