In che modo i computer possono calcolare la matematica esponenziale senza errori di overflow?


32

Studiando alcuni metodi di crittografia / decrittografia RSA, ho trovato questo articolo: un esempio dell'algoritmo RSA

Richiede questo per decodificare questo messaggio inserisci qui la descrizione dell'immagine

Il risultato totale di inserisci qui la descrizione dell'immagineè così grande, per una macchina a 64-bit / 32-bit, non credo che possa contenere un valore così grande in un registro. Come fa il computer a farlo senza un overflow?


Questa domanda era una domanda super utente della settimana .
Leggi la voce del blog per maggiori dettagli o contribuisci tu stesso al blog


6
Mi chiedo se otterresti una risposta migliore se questo fosse migrato su cs.stackexchange.com. Sembra che potrebbe adattarsi meglio a un sito CS / Math che è molto più focalizzato sui dettagli reali di cose basse che sono a un livello davvero basso.
Zoredache,

1
Questo è abbastanza valido per Super User.
James Mertz,

Risposte:


40

Poiché l'operazione del modulo intero è un omomorfismo ad anello ( Wikipedia ) da ℤ -> ℤ / nℤ,

(X * Y) mod N = (X mod N) * (Y mod N) mod N

Puoi verificarlo tu stesso con un po 'di semplice algebra. (Si noti che la finale modsul lato destro appare a causa della definizione di moltiplicazione in un anello modulare.)

I computer usano questo trucco per calcolare gli esponenziali negli anelli modulari senza dover calcolare un gran numero di cifre.

               / 1 I = 0,
               |
(X ^ I) mod N = <(X * (X ^ (I-1) mod N)) mod NI dispari,
               |
               \ (X ^ (I / 2) mod N) ^ 2 mod NI pari & I / = 0.

In forma algoritmica,

-- compute X^I mod N
function expmod(X, I, N)
    if I is zero
        return 1
    elif I is odd
        return (expmod(X, I-1, N) * X) mod N
    else
        Y <- expmod(X, I/2, N)
        return (Y*Y) mod N
    end if
end function

Puoi usarlo per calcolare (855^2753) mod 3233solo con i registri a 16 bit, se lo desideri.

Tuttavia, i valori di X e N in RSA sono molto più grandi, troppo grandi per essere inseriti in un registro. Un modulo è in genere lungo 1024-4096 bit! Quindi puoi fare in modo che un computer esegua la moltiplicazione nel modo "lungo", allo stesso modo in cui facciamo la moltiplicazione a mano. Solo invece di usare le cifre 0-9, il computer utilizzerà "parole" 0-2 16 -1 o qualcosa del genere. (L'uso di soli 16 bit significa che possiamo moltiplicare due numeri a 16 bit e ottenere il risultato completo a 32 bit senza ricorrere al linguaggio assembly. Nel linguaggio assembly, di solito è molto semplice ottenere il risultato completo a 64 bit o per un computer a 64 bit , il risultato completo a 128 bit.)

-- Multiply two bigints by each other
function mul(uint16 X[N], uint16 Y[N]):
    Z <- new array uint16[N*2]
    for I in 1..N
        -- C is the "carry"
        C <- 0
        -- Add Y[1..N] * X[I] to Z
        for J in 1..N
            T <- X[I] * Y[J] + C + Z[I + J - 1]
            Z[I + J - 1] <- T & 0xffff
            C <- T >> 16
        end
        -- Keep adding the "carry"
        for J in (I+N)..(N*2)
            T <- C + Z[J]
            Z[J] <- T & 0xffff
            C <- T >> 16
        end
    end
    return Z
end
-- footnote: I wrote this off the top of my head
-- so, who knows what kind of errors it might have

Questo moltiplicherà X per Y per un periodo di tempo approssimativamente uguale al numero di parole in X moltiplicato per il numero di parole in Y. Questo è chiamato tempo O (N 2 ). Se guardi l'algoritmo sopra e lo selezioni, è la stessa "lunga moltiplicazione" che insegnano a scuola. Non hai tabelle dei tempi memorizzate su 10 cifre, ma puoi comunque moltiplicare 1.926.348 x 8.192.004 se ti siedi e lo risolvi.

Moltiplicazione lunga:

    1,234
  x 5,678
---------
    9,872
   86,38
  740,4
6,170
---------
7,006,652

In realtà ci sono alcuni algoritmi più veloci in giro per la moltiplicazione ( Wikipedia ), come il metodo Fourier veloce di Strassen, e alcuni metodi più semplici che fanno addizione e sottrazione extra ma meno moltiplicazione, e quindi finiscono più velocemente nel complesso. Le librerie numeriche come GMP sono in grado di selezionare diversi algoritmi in base alla grandezza dei numeri: la trasformata di Fourier è solo la più veloce per i numeri più grandi, i numeri più piccoli usano algoritmi più semplici.


+1, ma ti manca un extra mod Nalla fine del Teorema del residuo cinese. ( (16 mod 5)non è uguale a (4 mod 5) * (4 mod 5): il primo è 1, il secondo è 16.)
ruakh,

@ruakh: corretto. Anche se voglio davvero dire, R / kR è isomorfo a R / k1R x R / k2R x ... R / knR, dove k1..kn sono coprimi a coppie, il loro prodotto è k e R è il dominio ideale principale. Ho sovraccaricato * per così tanto tempo che è difficile vederlo come tutt'altro che modulare. In altre parole, secondo le mie solite convenzioni notazionali modè superfluo.
Dietrich Epp,

1
@Synetech: Ma adoro quelle quattro parole: "Esercizio per il lettore".
Dietrich Epp,

1
(X * Y) mod N = (X mod N) * (Y mod N) mod Nè vero, ma non ha nulla a che fare con il teorema del residuo cinese.
Dennis,

1
@Dennis: ho chiarito la struttura del codice nella risposta ora. (Non è mai ambiguo per me, dal momento che l'ho scritto ...)
Dietrich Epp

9

La semplice risposta è che non possono, non da soli. Infatti, se prendi il concetto di una macchina x-bit, allora c'è un numero limitato di numeri che possono essere rappresentati da un numero limitato di bit, proprio come c'è un numero limitato di numeri che possono essere rappresentati da 2 cifre in il sistema decimale.

Detto questo, la rappresentazione al computer di numeri molto grandi è una componente importante del campo della crittografia. Esistono molti modi per rappresentare numeri molto grandi in un computer, ognuno vario quanto il successivo.

Ognuno di questi metodi ha diversi vantaggi e svantaggi e, sebbene non elencherò / non possa elencare tutti i metodi qui, ne presenterò uno molto semplice.

Supponiamo che un numero intero possa contenere solo valori compresi tra 0 e 99. Come si potrebbe rappresentare il numero 100? All'inizio questo può sembrare impossibile, ma è perché consideriamo solo una singola variabile. Se avessi un intero chiamato unitse uno chiamato hundreds, ho potuto facilmente rappresentare 100: hundreds = 1; units = 0;. Potrei facilmente rappresentare un numero più grande, come 9223: hundreds = 92; units = 23.

Mentre questo è un metodo semplice, si può sostenere che sia molto inefficiente. Come la maggior parte degli algoritmi che spingono i confini di ciò che un computer può fare, di solito è un tiro alla fune tra potenza (rappresentano un numero elevato) ed efficienza (recupero / archiviazione rapidi). Come ho detto prima, ci sono molti modi di rappresentare un gran numero di computer; basta trovare un metodo e sperimentarlo!

Spero che questo abbia risposto alla tua domanda!

Ulteriori letture:Questo articolo e questo potrebbero tornare utili per ulteriori informazioni.


3

Il modo in cui ciò può essere fatto (ci sono modi molto più veloci che coinvolgono ripetute quadrature e simili) è moltiplicando e dopo ogni moltiplicazione prendi il modulo. Finché il modulo quadrato è inferiore a 2 ^ 32 (o 2 ^ 64) questo non avrà mai un overflow.


3

Allo stesso modo che puoi.

Immagino che tu non sappia di persona cosa sia 342 * 189. Ma conosci i seguenti fatti:

9 * 2 = 18
9 * 4 = 36
9 * 3 = 27
8 * 2 = 16
8 * 4 = 32
8 * 3 = 24
1 * 2 = 2
1 * 4 = 4
1 * 3 = 3

18 + 360 + 2700 + 160 + 3200 + 24000 + 200 + 4000 + 30000 = 64638

Conoscendo questi semplici fatti e avendo imparato una tecnica per manipolarli, puoi fare un'aritmetica che altrimenti non potresti.

Allo stesso modo, un computer che non è in grado di gestire più di 64 bit di matematica alla volta può facilmente suddividere i problemi più grandi in pezzi più piccoli, fare quei pezzi più piccoli e rimetterli insieme per formare la risposta al più grande, in precedenza problema senza risposta.


0

Per quanto riguarda l'addizione e la sottrazione, molte CPU hanno un "carry bit" che viene impostato se l'operazione aritmetica è traboccata. Quindi, se un risultato richiederà 8 byte per l'archiviazione e la CPU è a 32 bit (che equls 4 byte a 8 bit), può fare due operazioni di aggiunta, prima sulla "parola bassa" e poi sulla "parola alta" con la punta di trasporto occupandosi dell'overflow. È necessario cancellare prima il bit di trasporto. Questo è uno dei motivi per cui CPU con bit più alti aumentano le prestazioni perché non è necessario farlo altrettanto.

Naturalmente questo è dovuto alla mia limitata esperienza con gli assemblatori con CPU a 8 bit. Non so come funzioni il carry-bit con le moderne CPU con istruzioni moltiplicate e divde. Anche le CPU RISC non Intel possono comportarsi diversamente.

Non so molto sulla matematica in virgola mobile, ma sostanzialmente i byte rappresentano un numero fisso di posti, ma non luoghi specifici. Ecco perché si chiama punto "mobile". Quindi, ad esempio, il numero 34459234 consumerebbe all'incirca lo stesso spazio di memoria di 3.4459234 o 3.4459234E + 20 (ovvero 3.4459234 x 10 ^ 20).

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.