Bagaimana cara mengubah bilangan bulat ke string di pangkalan apa pun?


203

Python memungkinkan pembuatan integer dengan mudah dari string basis tertentu

int(str, base). 

Saya ingin melakukan invers: membuat string dari integer , yaitu saya ingin beberapa fungsi int2base(num, base), sehingga:

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

Urutan nama / argumen fungsi tidak penting.

Untuk setiap nomor xdan pangkalan byang int()akan menerima.

Ini adalah fungsi yang mudah untuk ditulis: sebenarnya lebih mudah daripada menggambarkannya dalam pertanyaan ini. Namun, aku merasa aku pasti kehilangan sesuatu.

Aku tahu tentang fungsi bin, oct, hex, tapi aku tidak bisa menggunakannya karena beberapa alasan:

  • Fungsi-fungsi itu tidak tersedia pada versi Python yang lebih lama, yang saya perlukan kompatibilitasnya dengan (2.2)

  • Saya ingin solusi umum yang bisa disebut cara yang sama untuk pangkalan yang berbeda

  • Saya ingin mengizinkan pangkalan selain 2, 8, 16

Terkait


5
Anehnya tidak ada yang memberikan solusi yang bekerja dengan basis besar sewenang-wenang (1023). Jika Anda membutuhkannya, periksa solusi saya yang berfungsi untuk setiap basis (2 hingga inf) stackoverflow.com/a/28666223/1090562
Salvador Dali

Jawaban:


98

Jika Anda memerlukan kompatibilitas dengan versi Python kuno, Anda bisa menggunakan gmpy (yang menyertakan fungsi konversi int-to-string yang cepat dan sepenuhnya umum, dan dapat dibangun untuk versi kuno seperti itu - Anda mungkin perlu mencoba rilis yang lebih lama karena yang baru-baru ini belum diuji untuk rilis Python dan GMP yang terhormat, hanya yang agak baru), atau, untuk kecepatan yang lebih rendah tetapi lebih nyaman, gunakan kode Python - misalnya, paling sederhana:

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
Hanya dalam kasus (gmpy2) func Alex berbicara tentang tampaknya gmpy2.digits(x, base).
mlvljr

2
Perlu saya perhatikan bahwa beberapa kasus memerlukan basis> 36 dan penggalian harusdigs = string.digits + string.lowercase + string.uppercase
Paul

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

3
Adakah ide mengapa convert-base-N-to-string tidak disertakan secara default dalam Python? (Ada dalam Javascript.) Ya, kita semua bisa menulis implementasi kita sendiri, tapi saya sudah mencari-cari di situs ini dan di tempat lain, dan banyak dari mereka memiliki bug. Lebih baik memiliki satu versi teruji dan terkemuka yang termasuk dalam distribusi inti.
Jason S

4
@ lordscales91 Anda juga dapat menggunakan x //= baseyang berperilaku seperti /=di Python 2 dalam menjatuhkan desimal. Jawaban ini harus mencakup penafian bahwa ini untuk Python 2.
Noumenon

100

Yang mengejutkan, orang-orang hanya memberikan solusi yang mengubah basis-basis kecil (lebih kecil dari panjang alfabet Inggris). Tidak ada upaya untuk memberikan solusi yang mengkonversi ke basis sewenang-wenang dari 2 hingga tak terbatas.

Jadi, inilah solusi super sederhana:

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

jadi jika Anda perlu mengonversi beberapa nomor super besar ke pangkalan 577,

numberToBase(67854 ** 15 - 102, 577), Akan memberikan solusi yang tepat: [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],

Yang nantinya bisa Anda konversi menjadi basis yang Anda inginkan


Di perguruan tinggi saya membuat fungsi yang memformat basis di bawah 20 menjadi notasi standar, dan basis 20 dan lebih ke dalam 'desimal yang dibatasi titik dua'. Misalnya, int(4545,16)beri "11c1" dan int(4545,60)berikan "1:15:45". Dengan demikian fungsi melakukan tiga tugas: mengkonversi ke format desimal, komputer, dan timestamp.
Peter Raynham

1
Apa fungsi terbalik untuk metode ini?
Sohrab T

Ini tidak menjawab pertanyaan yang diajukan karena 3 alasan, 1: pertanyaan yang diajukan untuk fungsi perpustakaan yang ada bukan implementasi 2: pertanyaan yang diajukan untuk string, ini menghasilkan daftar 3: ini bukan kebalikan untuk int (str, base) builtin.
plugwash

@plugwash 1) di beberapa titik waktu Anda akan melihat bahwa kadang-kadang tidak ada fungsi perpustakaan builtin untuk melakukan hal-hal yang Anda inginkan, jadi Anda perlu menulis sendiri. Jika Anda tidak setuju, poskan solusi Anda sendiri dengan fungsi bawaan yang dapat mengonversi bilangan 10 basis ke basis 577. 2) ini disebabkan oleh kurangnya pemahaman apa arti angka dalam beberapa basis. 3) Saya mendorong Anda untuk berpikir sedikit mengapa dasar dalam metode Anda hanya berfungsi untuk n <= 36. Setelah Anda selesai, akan jelas mengapa fungsi saya mengembalikan daftar dan memiliki tanda tangan yang dimilikinya.
Salvador Dali

1
Ini tidak berfungsi untuk angka negatif, dan saya tidak yakin bagaimana membuatnya bekerja tanpa mengubahnya secara mendasar. Mungkin dengan menambahkan sedikit tanda, 1 atau -1, di bagian atas 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/

Perlu diketahui bahwa ini dapat menyebabkan

RuntimeError: maximum recursion depth exceeded in cmp

untuk bilangan bulat yang sangat besar.


5
Elegan dalam singkatnya. Tampaknya berfungsi di bawah python 2.2.3 untuk bilangan bulat non-negatif. Sejumlah negatif berulang berulang.
Mark Borgerding

+1 bermanfaat; memperbaiki masalah ketika angka tidak dimulai dengan '0'
sehe

4
Ini gagal secara diam-diam (a) ketika basis> len(numerals), dan (b) num % b, jika beruntung, < len(numerals). mis. meskipun panjang numeralsstring hanya 36 karakter, baseN (60, 40) mengembalikan '1k'sedangkan baseN (79, 40) memunculkan IndexError. Keduanya harus memunculkan semacam kesalahan. Kode harus direvisi untuk memunculkan kesalahan jika not 2 <= base <= len(numerals).
Chris Johnson

3
@ Ya, maksud saya adalah kode seperti yang ditulis gagal dengan cara yang sangat buruk (diam-diam, memberikan jawaban yang menyesatkan) dan dapat diperbaiki dengan mudah. Jika Anda mengatakan tidak akan ada kesalahan jika Anda tahu sebelumnya, pasti, itu btidak akan melebihi len(numerals), well, semoga sukses untuk Anda.
Chris Johnson

1
Penggunaan hubungan arus pendek di sini tampaknya membingungkan ... mengapa tidak hanya menggunakan pernyataan if ... salurannya return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]sama singkatnya.
Ian Hincks

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

46
Tapi apakah hanya tiga pangkalan itu?
Thomas Ahle

3
Ya, sayangnya Anda tidak dapat menentukan basis int khusus. Info lebih lanjut ada di sini: docs.python.org/library/string.html#formatstrings
Rost

3
Itu 0tidak perlu. Berikut dokumentasi Python 2: docs.python.org/2/library/string.html#format-string-syntax
Evgeni Sergeev

7
Anda dapat mencapai hasil yang sama dengan hex(100)[2:], oct(100)[2:]dan bin(100)[2:].
Sassan

2
@EvgeniSergeev: Hanya tidak perlu pada 2.7 / 3.1 +. Pada 2.6, posisi eksplisit (atau nama) diperlukan.
ShadowRanger

21

Jawaban bagus! Saya kira jawaban untuk pertanyaan saya adalah "tidak". Saya tidak melewatkan beberapa solusi yang jelas. Inilah fungsi yang akan saya gunakan yang mengembunkan ide-ide bagus yang diungkapkan dalam jawaban.

  • memungkinkan pemetaan karakter yang disediakan oleh penelepon (memungkinkan penyandian base64)
  • memeriksa negatif dan nol
  • memetakan bilangan kompleks menjadi tupel string


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
Bagaimana Anda mengonversi output base64 dari fungsi kami kembali ke integer?
detly

17

Rekursif

Saya akan menyederhanakan yang jawaban yang paling sebagai ke:

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

Dengan saran yang sama untuk RuntimeError: maximum recursion depth exceeded in cmpbilangan bulat yang sangat besar dan angka negatif. (Anda bisa menggunakan sys.setrecursionlimit(new_limit))

Berulang-ulang

Untuk menghindari masalah rekursi :

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

2
Refactored yang indah, dan tanpa perpustakaan.
Giampaolo Ferradini

Bukankah seharusnya kondisi berhenti return BS[0] if not nitu? Kalau-kalau Anda ingin menggunakan angka mewah, seperti yang saya lakukan :)
Arnaud P

@ArnaudP setuju. Yang ini bekerja untuk saya:return BS[n] if n < b else to_base(n // b) + BN[n % b]
Jens

15

Python tidak memiliki fungsi bawaan untuk mencetak integer di basis sewenang-wenang. Anda harus menulis sendiri jika Anda mau.


13

Anda dapat menggunakan baseconv.pydari proyek saya: https://github.com/semente/python-baseconv

Penggunaan sampel:

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

Ada beberapa konverter bultin sebagai contoh baseconv.base2, baseconv.base16dan baseconv.base64.


12

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


Solusi bagus Dalam kasus saya, saya menghindari numpy clacuntuk masalah waktu pemuatan. Preloading numpy lebih dari tiga kali lipat runtime evaluasi ekspresi sederhana di clac: misalnya clac 1+1 pergi dari sekitar 40ms ke 140ms.
Mark Borgerding

1
Perhatikan bahwa numpy.base_repr()memiliki batas 36 sebagai dasarnya. Kalau tidak, itu melempar aValueError
sbdchd

Yang cocok dengan batasan fungsi "int" bawaan. Basis yang lebih besar perlu memutuskan apa yang harus dilakukan ketika surat-surat habis,
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

Ini satu lagi dari tautan yang sama

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 tidak memperhitungkan kasus num == 0.
Craeft

3

Saya membuat paket pip untuk ini.

Saya sarankan Anda menggunakan bases.py saya https://github.com/kamijoutouma/bases.py yang terinspirasi oleh 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

lihat https://github.com/kamijoutouma/bases.py#known-basesalphabets untuk basis apa yang dapat digunakan

EDIT: tautan pipa https://pypi.python.org/pypi/bases.py/0.2.2


Ini berfungsi seperti pesona untuk basis yang dikenal ditentukan .
Agi Hammerthief

Sejauh ini, inilah jawaban terbaik! Dan terima kasih atas kemasan pipnya!
ɹɐʎɯɐʞ

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)

keluaran:

"1F"


other-basesama dengan other - base, jadi Anda harus menggunakanother_base
mbomb007

Juga, ini tidak berfungsi dengan benar jika decimalnol.
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

Solusi rekursif untuk mereka yang tertarik. Tentu saja, ini tidak akan bekerja dengan nilai-nilai biner negatif. Anda perlu menerapkan Komplemen Dua.

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

penjelasan

Dalam basis apa pun setiap angka sama dengan a1+a2*base**2+a3*base**3... "Misi" adalah untuk menemukan semua.

Untuk setiap N=1,2,3...kode mengisolasi aN*base**Ndengan "mouduling" oleh b b=base**(N+1) yang mengiris semua a lebih besar dari N, dan mengiris semua a bahwa serial mereka lebih kecil dari N dengan mengurangi setiap kali fungsi dipanggil oleh arusaN*base**N .

Basis% (basis-1) == 1 karenanya basis ** p% (basis-1) == 1 dan karenanya q * basis ^ p% (basis-1) == q dengan hanya satu pengecualian ketika q = basis-1 yang mengembalikan 0. Untuk memperbaikinya jika kembali 0 func memeriksa apakah 0 dari awal.


keuntungan

dalam sampel ini hanya ada satu perkalian (bukan pembagian) dan beberapa moudulueses yang relatif membutuhkan sedikit waktu.


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

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

tolong tambahkan beberapa informasi singkat bahwa apa yang Anda lakukan init khusus
Farhana

Meskipun ini dapat menjawab pertanyaan penulis, tidak ada beberapa kata yang menjelaskan dan / atau tautan ke dokumentasi. Cuplikan kode mentah tidak sangat membantu tanpa frasa di sekitarnya. Anda juga dapat menemukan cara menulis jawaban yang baik sangat membantu. Harap edit jawaban Anda.
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]   

Dalam fungsi ini Anda dapat dengan mudah mengkonversi angka desimal ke basis favorit Anda.
montaqami

Anda tidak perlu mengomentari jawaban Anda sendiri, Anda bisa mengeditnya untuk menambahkan penjelasan.
Pochmurnik

1

Berikut adalah contoh cara mengonversi sejumlah basis apa pun ke basis lain.

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

Satu lagi pendek (dan lebih mudah dimengerti):

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

Dan dengan penanganan pengecualian yang tepat:

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

Solusi lain, bekerja dengan basis 2 hingga 10, perlu modifikasi untuk basis yang lebih tinggi:

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

Contoh:

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

0

Ini adalah versi rekursif yang menangani bilangan bulat yang ditandatangani dan digit khusus.

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

String bukan satu-satunya pilihan untuk mewakili angka: Anda dapat menggunakan daftar bilangan bulat untuk mewakili urutan setiap digit. Mereka dapat dengan mudah dikonversi menjadi string.

Tidak ada jawaban yang menolak basis <2; dan sebagian besar akan berjalan sangat lambat atau crash dengan stack overflows untuk jumlah yang sangat besar (seperti 56789 ** 43210). Untuk menghindari kegagalan seperti itu, kurangi dengan cepat seperti ini:

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)

Kecepatannya, n_to_basesebanding dengan struntuk jumlah besar (sekitar 0,3 detik pada mesin saya), tetapi jika Anda membandingkanhex Anda mungkin akan terkejut (sekitar 0,3 ms pada mesin saya, atau 1000x lebih cepat). Alasannya adalah karena bilangan bulat besar disimpan dalam memori dalam basis 256 (byte). Setiap byte hanya dapat dikonversi ke string hex dua karakter. Penjajaran ini hanya terjadi untuk pangkalan yang memiliki kekuatan dua, itulah sebabnya ada kasus khusus untuk 2,8, dan 16 (dan base64, ascii, utf16, utf32).

Pertimbangkan digit terakhir dari string desimal. Bagaimana hubungannya dengan urutan byte yang membentuk integernya? Mari kita label byte s[i]dengan s[0]menjadi paling signifikan (little endian). Kemudian digit terakhir adalah sum([s[i]*(256**i) % 10 for i in range(n)]). Nah, itu terjadi 256 ** i diakhiri dengan 6 untuk i> 0 (6 * 6 = 36) sehingga digit terakhir adalah (s[0]*5 + sum(s)*6)%10. Dari ini, Anda dapat melihat bahwa digit terakhir tergantung pada jumlah semua byte. Properti nonlokal inilah yang membuat konversi ke desimal lebih sulit.


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

Untuk python3 kode Anda melakukan ini: baseConverter (0, 26) -> 'baseConverter (1, 26) ->' 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> 1 baseConverter (3, 26) -> 3 baseConverter (5, 26) -> 5 baseConverter (26, 26) -> 10 baseConverter (32, 26) -> 16
Drachenfels

0

Yah saya pribadi menggunakan fungsi ini, yang ditulis oleh saya

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

Ini adalah bagaimana Anda dapat menggunakannya

print(to_base(7, base=2))

Keluaran: "111"

print(to_base(23, base=3))

Keluaran: "212"

Silakan menyarankan perbaikan dalam kode saya.


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

0

Ini adalah pertanyaan lama tapi saya pikir saya akan membagikan pendapat saya karena saya merasa agak lebih sederhana daripada jawaban lain (baik untuk basis dari 2 hingga 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

Saya belum melihat ada konverter float di sini. Dan saya merindukan pengelompokan untuk selalu tiga digit.

MELAKUKAN:

-nomor dalam ekspresi ilmiah (n.nnnnnn*10**(exp)- '10'ituself.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string-function.

-basis 1 -> angka romawi?

-repr kompleks dengan agles

Jadi, inilah solusi saya:

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)

keluaran:

3ewfdnca0n6ld1ggvfgg

untuk mengkonversi ke basis apa pun, kebalikannya juga mudah.


Punya NameError: global name 'n' is not defined. Apakah divmod(x, n)seharusnya divmod(x, b)?
wjandrea
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.