La matematica dietro la conversione da qualsiasi base a qualsiasi base senza passare attraverso la base 10?


36

Ho esaminato la matematica dietro la conversione da qualsiasi base a qualsiasi base. Si tratta più di confermare i miei risultati che altro. Ho trovato quella che sembra essere la mia risposta su mathforum.org ma non sono ancora sicuro di averla bene. Ho la conversione da una base più grande a una base più piccola giù bene perché è semplicemente prendere la prima cifra moltiplicare per base che si desidera aggiungere la ripetizione della cifra successiva. Il mio problema si presenta quando si converte da una base più piccola a una base più grande. Quando lo fanno, parlano di come devi convertire la base più grande che desideri nella base più piccola che hai. Un esempio potrebbe andare dalla base 4 alla base 6, è necessario convertire il numero 6 in base 4 ottenendo 12. Quindi fai la stessa cosa che hai fatto durante la conversione da grande a piccolo. La difficoltà che ho con questo è che sembra che tu abbia bisogno di sapere quale sia un numero nell'altra base. Quindi avrei bisogno di sapere cosa c'è 6 nella base 4. Questo crea un grosso problema nella mia mente perché allora avrei bisogno di un tavolo. Qualcuno conosce un modo per farlo in un modo migliore.

Ho pensato che una conversione di base avrebbe aiutato, ma non riesco a trovare nulla che funzioni. E dal sito che ho trovato sembra che ti permetta di convertire da base a base senza passare attraverso la base 10 ma devi prima sapere come convertire il primo numero da base a base. Questo lo rende un po 'inutile.

I commentatori stanno dicendo che devo essere in grado di convertire una lettera in un numero. Se è così lo so già. Questo non è il mio problema comunque. Il mio problema è che per convertire una base grande in una base piccola devo prima convertire il numero base che ho nel numero base che voglio. Nel fare ciò, ho sconfitto lo scopo perché se ho la possibilità di convertire queste basi in altre basi ho già risolto il mio problema.

Modifica: ho capito come convertire da basi inferiori o uguali a 10 in altre basi inferiori o uguali a 10. Posso anche passare da una base maggiore di 10 a qualsiasi base inferiore o uguale a 10. Il problema inizia quando si converte da una base maggiore di 10 a un'altra base maggiore di 10. O passando da una base inferiore a 10 a una base maggiore di 10. Non ho bisogno di codice, ho solo bisogno della matematica di base che può essere applicato al codice.


1
Questa domanda è sull'argomento di questo forum?
Andrej Bauer,

2
La procedura è banale fintanto che è possibile eseguire addizioni e moltiplicazioni nella base di destinazione. Se non puoi, non penso sia possibile.
Karolis Juodelė,

9
A Griffin dovrebbe prima essere detto ciò che molti studenti devono ascoltare: i numeri esistono senza essere rappresentati in una base . Quindi la risposta è chiara: abbiamo bisogno di algoritmi, uno per convertire una rappresentazione di un numero in una data base nel numero (cioè qualcosa che prende un stringe restituisce un int), e un algoritmo che prende un numero e restituisce la sua rappresentazione in una data base.
Andrej Bauer,

1
@AndrejBauer La domanda riguarda CS: anche se non è formulata in questo modo, questa è una domanda su un algoritmo da convertire tra rappresentazioni numeriche. [Nota non correlata: ho eliminato un sacco di commenti confusi. Griffin: modifica la tua domanda per aggiornarla. Altri: per favore, portalo in chat .]
Gilles 'SO- smetti di essere malvagio' il

1
@Griffin È passato molto tempo dalla tua domanda originale. Spero che tu abbia trovato la tua risposta In tal caso, potrebbe essere una buona idea aggiornare e accettare una risposta o pubblicare la tua. Nel frattempo ho trovato un paio di idee molto belle (parlando dell'implementazione in C ++) negli archivi Code Jam di Google. Alcune soluzioni a questo problema sono code.google.com/codejam/contest/32003/dashboard
IsaacCisneros,

Risposte:


45

Questa mi sembra una domanda basilare, quindi scusami se ti insegno un po '. Il punto più importante da imparare qui è che un numero non è la sua rappresentazione numerica . Un numero è un oggetto matematico astratto, mentre la sua rappresentazione numerica è una cosa concreta, vale a dire una sequenza di simboli su un foglio (o una sequenza di bit nella memoria di calcolo, o una sequenza di suoni che emetti quando comunichi un numero). Ciò che ti confonde è il fatto che non vedi mai un numero ma sempre la sua rappresentazione numerica. Quindi finisci per pensare che il numero sia la rappresentazione.

Pertanto, la domanda corretta da porre non è "come convertire da una base all'altra", ma piuttosto "come faccio a scoprire quale numero è rappresentato da una determinata stringa di cifre" e "come trovo la rappresentazione delle cifre di un dato il numero ".

Quindi produciamo due funzioni in Python, una per convertire una rappresentazione numerica in un numero e un'altra per fare il contrario. Nota: quando eseguiamo la funzione Python stamperà ovviamente sullo schermo il numero ottenuto nella base 10. Ma questo non significa che il computer mantenga i numeri nella base 10 (non lo è). È irrilevante il modo in cui il computer rappresenta i numeri.

def toDigits(n, b):
    """Convert a positive number n to its digit representation in base b."""
    digits = []
    while n > 0:
        digits.insert(0, n % b)
        n  = n // b
    return digits

def fromDigits(digits, b):
    """Compute the number given by digits in base b."""
    n = 0
    for d in digits:
        n = b * n + d
    return n

Proviamo questi:

>>> toDigits(42, 2)
[1, 0, 1, 0, 1, 0]
>>> toDigits(42, 3)
[1, 1, 2, 0]
>>> fromDigits([1,1,2,0],3)
42

Grazie alle funzioni di conversione, il problema si risolve facilmente:

def convertBase(digits, b, c):
    """Convert the digits representation of a number from base b to base c."""
    return toDigits(fromDigits(digits, b), c)

Un test:

>>> convertBase([1,1,2,0], 3, 2) 
[1, 0, 1, 0, 1, 0]

Nota: non abbiamo superato la rappresentazione in base 10! Abbiamo convertito la rappresentazione di base nel numero, quindi il numero in base c . Il numero non era in nessuna rappresentazione. (In realtà lo era, il computer doveva rappresentarlo in qualche modo, e lo rappresentava usando segnali elettrici e cose funky che si verificano nei chip, ma certamente quelli non erano 0 e 1.)Bc


4
Questo non mi convince al 100%. In effetti, hai convertito il numero in una rappresentazione (anche se puoi affermare di non sapere di cosa si tratta) perché i computer non sono matematici platonici e il tuo algoritmo non può convertire una sequenza arbitraria di cifre dalla base alla base b 2 ; può solo convertire sequenze rappresentabili dalla macchina per calcestruzzo. Python è incredibilmente flessibile; C non sarebbe stato così indulgente. È perfettamente valido chiedere come convertire stringhe arbitrarie da b 1 a b 2 ; tuttavia, ciò è possibile solo in tempo lineare, tranne per alcune combinazioni di basi (ad es. 2 <-> 16)B1B2B1B2
rici

1
È valido porre la domanda, ma per trovare la risposta giusta è meglio essere consapevoli del fatto che i numeri sono entità astratte.
Andrej Bauer,

2
Questo fa passare il numero attraverso la base 10 rappresentazione, i fromDigitsritorni il numero in base 10.
apnorton

8
@anorton: No, sicuramente no . Python stampa il numero sullo schermo nella rappresentazione di 10 cifre di base, ma il numero stesso non viene memorizzato in questo modo. Quello che sto cercando di ottenere è che è irrilevante il modo in cui i numeri sono implementati all'interno di Python. Non importa. L'unica cosa che conta è che si comportano come numeri.
Andrej Bauer l'

3
Finalmente una soluzione generale per qualsiasi base e non limitata a casi d'uso particolari, basi inferiori a 36 o casi in cui è possibile trovare abbastanza simboli univoci.
J.Money,

21

Penso che il modo migliore per capirlo sia discutere con un alieno (almeno per analogia).

La definizione è un numero nella base bXB significa che è una stringa di cifre < b .X<B

Esempi La stringa di cifre 10010011011 è un numero nella base 2, la stringa 68416841531 è un numero nella base 10, BADCAFE è un numero nella base 16.

Ora supponiamo che io sia cresciuto sul pianeta QUUX, dove a tutti viene insegnato a lavorare in per tutta la vita, e ti incontro che è abituato a basare b . Quindi mi mostri un numero e cosa devo fare? Ho bisogno di un modo per interpretarlo:qB

Definizione Posso interpretare un numero nella base (Nota: b è un numero nella base q ) con la seguente formulaBBq

[[ε]]=0[[S¯d]]=[[S¯]]×B+d

dove indica la stringa vuota e ˉ s d indica una stringa che termina con la cifra d . Vedi la mia prova che l'aggiunta aggiunge per un'introduzione a questa notazione.εS¯dd

Quindi cosa è successo qui? Mi hai dato un numero in base e l'ho interpretato in base q senza alcuna strana filosofia su cosa siano veramente i numeri.Bq

Chiave La chiave di ciò è che e + I sono funzioni che operano su numeri q di base . Si tratta di semplici algoritmi definiti ricorsivamente su numeri q di base (stringhe di cifre).×+qq


Questo può sembrare un po 'astratto dal momento che ho usato variabili piuttosto che numeri reali in tutto. Quindi supponiamo che tu sia una creatura base 13 (usando i simboli ) e io sono abituato a base 7 (che è molto più sensibile) usando i simboli α β γ δ ρ ζ ξ .0123456789XYZαβγδρζξ

Quindi ho visto il tuo alfabeto e l'ho tabulato così:

0α1β2γ3δ4ρ5ζ6ξ7βα8ββ9βγXβδYβρZβζ

βξ

60Z8

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ

βζ×βξ

Tabella di moltiplicazione Quux

×βγδρζξββγδρζξγγρξβββδβζδδξβγβζγβγρρρβββζγγγξδδζζβδγβγξδρργξξβζγρδδργζββαβαγαδαραζαξα

βζ×βξ

βζ×βξξγρβζδβγγ

quindi sono arrivato così lontano

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ

Ora devo eseguire l'aggiunta usando l'algoritmo che è stato menzionato prima:

δβγββδγδ

così

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ=ξ(βξ)3+α(βξ)2+δγδ

[[60Z8]]=ζδξγρ.

qBq


1
Beh, era una buona dose di linee ondulate. Come farei comunque a farlo fare al computer?
Griffin,

1
@Griffin, penso che tu stia facendo questa (strana) domanda prematuramente. Scegli un linguaggio di programmazione e scrivi l'algoritmo per l'addizione e la moltiplicazione sui numeri di base q (rappresentati come elenchi di cifre), quindi definisci una funzione per interpretare le cifre di base b in numeri di base q e interpretare i numeri di base b in numeri di base q. Ho spiegato tutto questo.

Il fatto è che conosco il concetto che stai cercando di ritrarre. Il mio problema è che il mio computer non può usare le tue linee ondulate.
Griffin,

So cosa hai spiegato, ma metterlo in pratica è molto più difficile. Vedi che definire quelle cifre non è così facile.
Griffin,

1
Inoltre, perché hai lasciato cadere la cifra alfa nella posizione più significativa? Poiché 6 = & xi ;, non sarebbe 7 = & alpha; & alpha ;?
Giovanni Botta,

9

Questo è solo un refactoring (Python 3) del codice di Andrej . Nel codice di Andrej i numeri sono rappresentati attraverso un elenco di cifre (scalari), mentre nei seguenti codici i numeri sono rappresentati attraverso un elenco di simboli presi da una stringa personalizzata :

def v2r(n, base): # value to representation
    """Convert a positive number to its digit representation in a custom base."""
    b = len(base)
    digits = ''
    while n > 0:
        digits = base[n % b] + digits
        n  = n // b
    return digits

def r2v(digits, base): # representation to value
    """Compute the number represented by string 'digits' in a custom base."""
    b = len(base)
    n = 0
    for d in digits:
        n = b * n + base[:b].index(d)
    return n

def b2b(digits, base1, base2):
    """Convert the digits representation of a number from base1 to base2."""
    return v2r(r2v(digits, base1), base2)

Per eseguire una conversione da valore a rappresentazione in una base personalizzata:

>>> v2r(64,'01')
'1000000'
>>> v2r(64,'XY')
'YXXXXXX'
>>> v2r(12340,'ZABCDEFGHI') # decimal base with custom symbols
'ABCDZ'

Per eseguire una conversione dalla rappresentazione (in una base personalizzata) al valore:

>>> r2v('100','01')
4
>>> r2v('100','0123456789') # standard decimal base
100
>>> r2v('100','01_whatevr') # decimal base with custom symbols
100
>>> r2v('100','0123456789ABCDEF') # standard hexadecimal base
256
>>> r2v('100','01_whatevr-jklmn') # hexadecimal base with custom symbols
256

Per eseguire una conversione di base da una base personalizzata a un'altra:

>>> b2b('1120','012','01')
'101010'
>>> b2b('100','01','0123456789')
'4'
>>> b2b('100','0123456789ABCDEF','01')
'100000000'

1
Benvenuti nel sito e grazie per il vostro contributo. Tuttavia, produrre codice sorgente ben ottimizzato non è ciò di cui tratta questo sito. Il codice di Andrej rende i concetti chiari, che è ciò che è necessario per la sua risposta, ma migliorando il codice al di là che è una questione di programmazione, piuttosto che di computer science .
David Richerby,

1
@DavidRicherby Sono in parte d'accordo, ma questo contributo è stato troppo lungo per un commento e il suo posto migliore dove trovarsi è da qualche parte vicino alla risposta di Andrej, ecco perché l'ho pubblicato qui. Comunque, se pensi che sia meglio, potrei convertirlo in un commento con un link al codice, ma non sarebbe un eccesso di purismo?
mmj,

1

L'operazione fondamentale della conversione di base è l' toDigits()operazione della risposta @AndrejBauer. Tuttavia, per realizzarlo non è necessario creare un numero nella rappresentazione interna dei numeri, che è fondamentalmente una conversione da e verso la rappresentazione di base 2. È possibile effettuare le operazioni necessarie nella rappresentazione di base originale.

Quindi il primo passo è eseguire ripetute operazioni di divisione del modulo

def convertBase(n,original_base,destination_base):
    digits = []    
    while not is_zero(n):
        digits.insert(0,modulo_div(n,original_base,destination_base))
    return digits

Poiché la rappresentazione interna è composta da cifre, è necessario eseguire una funzione specilaizzata per verificare zero

def is_zero(n):
    for d in n:
        if d != 0:
            return False
    return True

Alla fine si deve fare l'operazione modulo_div che è in realtà la divisione standard per base di destinazione come abbiamo imparato a scuola.

def modulo_div(n,original_base,destination_base):
    carry = 0
    for i in range(len(n)):
        d = n[i]
        d+=original_base*carry 
        carry = d%destination_base 
        d=(d//destination_base)
        n[i] = d
        #print(i,d,carry)
    return carry

solo un test di verifica per verificare che il codice sia corretto:

print(convertBase([1,1,2,0], 3, 2))
#[1, 0, 1, 0, 1, 0]

print(convertBase([1, 0, 1, 0, 1, 0], 2, 3))
#[1, 1, 2, 0]

Grazie per la pubblicazione, ma tieni presente che non siamo un sito di codifica, quindi un grosso blocco di codice non è appropriato come risposta qui. Soprattutto quando la domanda dice esplicitamente: "Non ho bisogno di codice, ho solo bisogno della matematica di base dietro di esso."
David Richerby,

@DavidRicherby Ho provato ad aggiungere del testo.
Xavier Combelle,

Grazie. E vedo che c'è un sacco di codice in questa pagina, nonostante quello che ho detto!
David Richerby, il

0

Conosco un modo semplice per eseguire la conversione di base che non richiede un programma per computer. È definendo un modo per convertire da qualsiasi base a base 2 e viceversa e quindi convertendo da una base a un'altra base convertendo prima dalla prima base alla base 2, quindi convertendo dalla base 2 all'altra base. 2 è così facile da moltiplicare o dividere per in qualsiasi base.

Per convertire da qualsiasi base a base 2, tutto ciò che devi fare è riconoscere che per qualsiasi numero, se prendi la sua notazione di base 2 e inizi da 0 e poi per ogni cifra nell'ordine da sinistra a destra doppia se quella cifra è zero e raddoppiare di aggiungere 1 se quella cifra è 1, si arriva a quel numero stesso. Ora dato quel numero in qualsiasi base, puoi dividere per 2 in quella base per ottenere un quoziente e il resto. Se il resto è 1, l'ultima cifra binaria è 1 e se il resto è 0, l'ultima cifra binaria è 0. Dividi nuovamente per 2. Se il resto è 1, la seconda ultima cifra è 1 e se il resto è 0, la seconda ultima cifra è 0 e così via fino a ottenere un quoziente di 0.

Per convertire dalla base 2 a qualsiasi base, tutto ciò che devi fare è in quella base, iniziare da 0, quindi per ogni cifra binaria che va da sinistra a destra, raddoppia in quella base se quella cifra è 0 e raddoppia quindi aggiungi 1 in quella base se quella cifra è 1.


2 is so easy to multiply or divide by in any base.Non vedo che per basi dispari che sono più di una per qualsiasi potenza di due (11 e 13, per cominciare).
Greybeard,

0

È possibile convertire dalla base n alla base 10 senza alcuna conversione in una base intermedia.

Per convertire dalla base n alla base 9, ad esempio, si prende l'algoritmo per la conversione in base 10 e si sostituisce "10" con "9". Lo stesso per qualsiasi altra base.

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.