Bir tamsayıyı herhangi bir tabandaki dizeye nasıl dönüştürebilirim?


203

Python, verilen bir taban dizesinden bir tamsayının kolayca oluşturulabilmesini sağlar.

int(str, base). 

Ters yapmak istiyorum: bir tamsayı bir dize oluşturma , yani ben int2base(num, base)böyle bir işlev istiyorum :

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

İşlev adı / bağımsız değişken sırası önemsizdir.

xKabul bedecek herhangi bir sayı ve taban için int().

Bu yazmak kolay bir işlevdir: aslında bu soruda tanımlamaktan daha kolaydır. Ancak, bir şeyleri kaçırmam gerektiğini hissediyorum.

Ben işlevleri hakkında biliyorum bin, oct, hex, ama birkaç nedenden dolayı bunları kullanamazsınız:

  • Bu işlevler (2.2) ile uyumluluğa ihtiyacım olan Python'un eski sürümlerinde mevcut değildir.

  • Farklı üsler için aynı şekilde çağrılabilecek genel bir çözüm istiyorum

  • 2, 8, 16 dışındaki bazlara izin vermek istiyorum

İlişkili


5
Şaşırtıcı bir şekilde, hiç kimse keyfi büyük taban ile çalışan bir çözüm sunmadı (1023). İhtiyacınız olursa her baz istasyonunda (2'den inf'ye) çalışan çözümümü kontrol edin stackoverflow.com/a/28666223/1090562
Salvador Dali

Yanıtlar:


98

Python'un eski sürümleriyle uyumluluğa ihtiyacınız varsa, gmpy'yi kullanabilirsiniz (hızlı, tamamen genel bir dizeye dönüştürme işlevini içerir ve bu eski sürümler için oluşturulabilir - daha eski sürümleri denemeniz gerekebilir. son zamanlar saygıdeğer Python ve GMP sürümleri için test edilmedi, sadece biraz yeni olanlar) veya daha düşük hızda ancak daha fazla rahatlık için Python kodunu kullanın - örneğin, en basit şekilde:

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
Sadece (gmpy2) durumunda Alex'in bahsettiği fon gibi görünüyor gmpy2.digits(x, base).
mlvljr

2
Bazı vakaların 36'dan büyük bir tabana ihtiyacı olduğu dikkatimi çekti ve bu nedenle kazılar olmalıdigs = string.digits + string.lowercase + string.uppercase
Paul

4
(veya string.digits + string.letters)
kojiro

3
Convert-base-N-to-string'in neden Python'a varsayılan olarak dahil edilmediğine dair bir fikriniz var mı? (Javascript'te.) Evet, hepimiz kendi uygulamamızı yazabiliriz, ancak bu sitede ve başka yerlerde arama yapıyorum ve çoğunda hatalar var. Çekirdek dağıtımında test edilmiş, saygın bir versiyona sahip olmak daha iyidir.
Jason S

4
@ lordscales91 Ondalık sayıları düşürürken Python 2'deki x //= basegibi davranır da kullanabilirsiniz /=. Bu cevap Python 2 için bir sorumluluk reddi içermelidir.
Noumenon

100

Şaşırtıcı bir şekilde, insanlar sadece küçük üslere (İngiliz alfabesinin uzunluğundan daha küçük) dönüşen çözümler veriyorlardı. Herhangi bir keyfi tabana 2'den sonsuza dönüşen bir çözüm verme denemesi olmadı.

İşte size süper basit bir çözüm:

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

yani çok büyük bir sayıyı tabana dönüştürmeniz gerekiyorsa 577,

numberToBase(67854 ** 15 - 102, 577), size doğru bir çözüm verecektir: [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] ,

Daha sonra istediğiniz herhangi bir tabana dönüştürebilirsiniz.


Kolejde 20'nin altında üsleri standart gösterime ve 20 ve daha büyük üsleri 'kolonla sınırlandırılmış ondalığa' dönüştüren bir işlev buldum. Örneğin, int(4545,16)"11c1" ve int(4545,60)"1:15:45" verdi. Böylece fonksiyon üçlü görev yaptı: ondalık, bilgisayarlı ve zaman damgası formatlarına dönüştürme.
Peter Raynham

1
Bu yöntemin ters fonksiyonu nedir?
Sohrab T

Bu, 3 nedenden dolayı sorulan soruya cevap vermez, 1: varolan bir kütüphane işlevi için sorulan soru bir uygulama değil 2: bir dize için sorulan soru, bu bir liste 3 üretir: bu int için ters değildir (str, baz) yerleşik.
Ocak'ta

@plugwash 1) bir noktada, bazen istediğiniz şeyleri yapmak için yerleşik bir kütüphane işlevi olmadığını fark edeceksiniz, bu yüzden kendiniz yazmanız gerekir. Eğer katılmıyorsanız, temel bir 10 sayısını temel 577'ye dönüştürebilen yerleşik bir işlevle kendi çözümünüzü gönderin. 2) bunun nedeni, bazı temellerdeki bir sayının ne anlama geldiğinin anlaşılmamasıdır. 3) Metodunuzdaki bazın neden sadece n <= 36 için çalıştığını biraz düşünmenizi öneririm. İşiniz bittiğinde, fonksiyonumun neden bir liste döndürdüğü ve imzası olduğu açık olacaktır.
Salvador Dali

1
Bu negatif sayılar için işe yaramaz ve temelde değiştirmeden nasıl çalışacağından emin değilim. Belki üstüne 1 veya -1, bir bit işareti ekleyerek 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])

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

Lütfen bunun yol açabileceğini unutmayın.

RuntimeError: maximum recursion depth exceeded in cmp

çok büyük tamsayılar için.


5
Özünde zarif. Negatif olmayan tamsayılar için python 2.2.3 altında çalışıyor gibi görünüyor. Negatif bir sayı sonsuza dek tekrar eder.
Mark Borgerding

+1 yararlı; sayılar '0' ile başlamadığında bir sorun
çözüldü

4
Bu, (a) baz> len(numerals)olduğunda ve (b) num % bşans eseri < olduğunda sessizce başarısız olur len(numerals). örneğin, numeralsdize yalnızca 36 karakter uzunluğunda olsa da, baseN (60, 40) döndürülürken '1k'baseN (79, 40) bir IndexError. Her ikisi de bir tür hataya yol açmalıdır. Eğer bir hata oluşması için kod revize edilmelidir not 2 <= base <= len(numerals).
Chris Johnson

3
@osa, benim açımdan kodun çok kötü bir şekilde başarısız olduğu (sessizce, yanıltıcı cevap vererek) ve kolayca düzeltilebilir. Eğer önceden biliyor olsaydınız hiçbir hata olmayacağını söylüyorsanız, kesin olarak, bu size iyi şansı bgeçmeyecektir len(numerals).
Chris Johnson

1
Burada kısa devre kullanımı gereksiz yere kafa karıştırıcı görünüyor ... neden sadece if ifadesini kullanmıyorsunuz ... hat return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]da aynı derecede kısa.
Ian Hincks

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

46
Ama sadece bu üç üs?
Thomas Ahle

3
Evet, maalesef özel int tabanı belirleyemezsiniz. Daha fazla bilgi burada: docs.python.org/library/string.html#formatstrings
Rost


7
Sen ile aynı sonuçlar elde edebilirsiniz hex(100)[2:], oct(100)[2:]ve bin(100)[2:].
Sassan

2
@EvgeniSergeev: 2.7 / 3.1 + 'da sadece gereksiz. 2.6'da açık konum (veya ad) gereklidir.
ShadowRanger

21

Harika cevaplar! Sorumun cevabının "hayır" olduğunu tahmin ediyorum. İşte cevaplarda ifade edilen iyi fikirleri yoğunlaştıracak fonksiyon.

  • karakterlerin arayan tarafından eşlenmesine izin ver (base64 kodlamasına izin verir)
  • negatif ve sıfır kontrolü
  • Karmaşık sayıları karakter dizileriyle eşler


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
İşlevimizin base64 çıktısını nasıl bir tamsayıya dönüştürebilirsiniz?
detly

18

Recursive

Ben ediyorum basitleştirmek en olarak cevap için:

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

RuntimeError: maximum recursion depth exceeded in cmpÇok büyük tamsayılar ve negatif sayılar için aynı tavsiyeyle . (Kullanabilirsiniz sys.setrecursionlimit(new_limit))

tekrarlayan

Özyineleme sorunlarından kaçınmak için :

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

2
Güzelce yeniden düzenlenmiş ve kütüphane olmadan.
Giampaolo Ferradini

Durma koşulu return BS[0] if not no zaman olmamalı mı ? Tam da benim gibi süslü rakamlar kullanmak istiyorsanız :)
Arnaud P

@ArnaudP kabul etti. Bu benim için çalışıyor:return BS[n] if n < b else to_base(n // b) + BN[n % b]
Jens

15

Python'un keyfi bir tabanda tamsayı yazdırmak için yerleşik bir işlevi yoktur. İsterseniz kendiniz yazmak zorunda kalacaksınız.


13

Projemden kullanabilirsiniz baseconv.py: https://github.com/semente/python-baseconv

Örnek kullanım:

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

Örneğin baseconv.base2, bazı bulten dönüştürücüler vardır baseconv.base16ve baseconv.base64.


12

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


Güzel çözüm. Benim durumumda, clacyükleme zamanı endişeleri için uyuşukluktan kaçınıyordum . clac 1+1 Numpy'yi clac'daki basit ifade değerlendirme çalışma süresinin üç katından fazla önyükleme: örneğin yaklaşık 40ms ila 140ms arasında gitti.
Mark Borgerding

1
Not numpy.base_repr()kaidesi olarak 36 bir sınırı vardır. Aksi takdirde bir atarValueError
sbdchd

Hangi yerleşik "int" işlevi sınırlamasıyla eşleşir. Daha büyük üsler, harfler bittiğinde ne yapılacağına karar vermeyi gerektirir,
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

İşte aynı bağlantıdan bir tane daha

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, num == 0 durumunu açıklamaz.
Craeft

3

Bunun için bir pip paketi yaptım.

Bases.js'den esinlenen bases.py https://github.com/kamijoutouma/bases.py adresimi kullanmanızı tavsiye ederim.

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

bkz. https://github.com/kamijoutouma/bases.py#known-basesalphabets hangi bazların kullanılabilir olduğu

DÜZENLE: pip bağlantısı https://pypi.python.org/pypi/bases.py/0.2.2


Bu, bilinen bilinen bazlar için bir cazibe gibi çalışır .
Agi Hammerthief

Bu açık ara en iyi cevap! Ve pip ambalajı için teşekkürler!
ɹɐʎɯɐʞ

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)

çıktı:

"1F"


other-baseaynı other - baseolmalıdır, bu yüzden kullanmalısınızother_base
mbomb007

Ayrıca, decimalsıfır ise bu düzgün çalışmaz .
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

İlgilenenler için özyinelemeli bir çözüm. Tabii ki, bu negatif ikili değerlerle çalışmaz. Two's Complement'ı uygulamanız gerekir.

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

açıklama

Herhangi bir temelde her sayı eşittir a1+a2*base**2+a3*base**3..."misyon" tüm a's bulmaktır.

Her N=1,2,3...kod için aN*base**Nb=base**(N+1) tüm a'nın N'den büyük olduğu dilimin b tarafından "mouduling" akımın çağrıldığı çağrıyı azaltarak, seri'nin N'den küçük olduğu tüm a 'ların dilimlenmesi aN*base**N.

Baz% (base-1) == 1 bunun için base ** p% (base-1) == 1 ve bunun için q * base ^ p% (base-1) == q, q = base-1 olduğunda yalnızca bir istisna dışında 0 döndürmesi durumunda fonkun başlangıçtan itibaren 0 olup olmadığını kontrol etmek için.


avantajları

bu örnekte sadece bir çarpma (bölme yerine) ve nispeten az miktarda zaman alan bazı mouduluezler vardır.


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

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

lütfen özel init yaptığınız bazı kısa bilgiler ekleyin
Farhana

Bu, yazarların sorusunu cevaplasa da, açıklayıcı kelimeler ve / veya belgelere bağlantılar içermez. Ham kod parçacıkları, çevrelerindeki bazı ifadeler olmadan çok yararlı değildir. Ayrıca bulabilirsiniz iyi bir cevap yazmayı çok yararlı. Lütfen cevabınızı düzenleyin.
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]   

Bu fonksiyonda, herhangi bir ondalık sayıyı kolayca favori tabanınıza dönüştürebilirsiniz.
montaqami

Kendi cevabınıza yorum yapmak zorunda değilsiniz, sadece açıklama eklemek için düzenleyebilirsiniz.
Pochmurnik

1

Aşağıda, herhangi bir baz sayısının başka bir tabana nasıl dönüştürüleceğine ilişkin bir örnek verilmiştir.

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

Başka bir kısa (ve imo'yu anlamak daha kolay):

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

Ve uygun istisna yönetimi ile:

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

Başka bir çözüm, taban 2 ila 10 ile çalışır, daha yüksek bazlar için modifikasyon gerektirir:

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

Misal:

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

0

İşte imzalı tam sayıları ve özel rakamları işleyen özyinelemeli bir sürüm.

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

Dizeler sayıları temsil etmek için tek seçenek değildir: her basamağın sırasını temsil etmek için bir tamsayı listesi kullanabilirsiniz. Bunlar kolayca bir dizgeye dönüştürülebilir.

Cevapların hiçbiri <2 tabanını reddetmez; ve çoğu çok yavaş çalışır veya çok büyük sayılar için yığın taşmasıyla kilitlenir (56789 ** 43210 gibi). Bu tür arızaları önlemek için şu şekilde hızlı bir şekilde azaltın:

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, büyük sayılarla n_to_basekarşılaştırılabilir str(makinemde yaklaşık 0,3 sn), ancak size karşı karşılaştırırsanız hexşaşırabilirsiniz (makinemde yaklaşık 0,3 ms veya 1000 kat daha hızlı). Bunun nedeni, büyük tamsayının 256 (bayt) tabanındaki bellekte depolanmasıdır. Her bayt basitçe iki karakterli onaltılık bir dizeye dönüştürülebilir. Bu hizalama yalnızca ikisinin gücü olan üsler için gerçekleşir, bu nedenle 2,8 ve 16 (ve base64, ascii, utf16, utf32) için özel durumlar vardır.

Ondalık bir dizenin son basamağını düşünün. Tamsayısını oluşturan bayt dizisi ile nasıl ilişkilidir? Diyelim bayt etiketlemek s[i]ile s[0]en önemsiz (küçük endian) olmak. Sonra son rakamsum([s[i]*(256**i) % 10 for i in range(n)]) . Eh, 256 ** i i> 0 (6 * 6 = 36) için 6 ile biter, böylece son basamak olur (s[0]*5 + sum(s)*6)%10. Bundan, son basamağın tüm baytların toplamına bağlı olduğunu görebilirsiniz. Bu yerel olmayan özellik ondalık sayıya dönüştürmeyi zorlaştırır.


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

Python3 için kodunuz bunu yapar: baseConverter (0, 26) -> '' baseConverter (1, 26) -> '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' python2 için (bu: 26) '' -> 1 baz Konvertör (3, 26) -> 3 baz Konvertör (5, 26) -> 5 baz Konvertör (26, 26) -> 10 baz Konvertör (32, 26) -> 16
Drachenfels

0

Ben şahsen yazdığım bu işlevi şahsen kullanıyorum

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

Bu şekilde kullanabilirsiniz

print(to_base(7, base=2))

Çıktı: "111"

print(to_base(23, base=3))

Çıktı: "212"

Lütfen kodumda iyileştirmeler önermekten çekinmeyin.


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

0

Bu eski bir soru ama diğer cevapların (2'den 36'ya kadar olan bazlar için iyi) biraz daha basit olduğunu düşündüğüm için benim payımı paylaşacağımı düşündüm:

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

0

Bunun eski bir gönderi olduğunu biliyorum, ama her ihtimale karşı çözümümü burada bırakıyorum.

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)

-1

Burada herhangi bir şamandıra dönüştürücüsü görmedim. Ve her zaman üç basamaklı gruplamayı kaçırdım.

YAPMAK:

-Bilimsel ifadedeki numaralar (n.nnnnnn*10**(exp)-'10' olduğuself.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string fonksiyonlu.

baz 1 -> roma rakamları?

- Agllerle kompleks kompleksi

İşte benim çözümüm:

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)

çıktı:

3ewfdnca0n6ld1ggvfgg

herhangi bir tabana dönüştürmek için tersi de kolaydır.


Anladım NameError: global name 'n' is not defined. Olması divmod(x, n)gerekiyor divmod(x, b)mu?
wjandrea
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.