mercoledì 16 maggio 2012

Algoritmo della settimana: Moltiplicazione Karatsuba veloce


Introduzione

Tipicamente moltiplicando due numeri di n cifre richiedono moltiplicazioni n2. Che in realtà è come noi, esseri umani, moltiplicare i numeri. Diamo uno sguardo di un esempio nel caso in cui abbiamo a moltiplicare due numeri a 2 cifre.

1.= 12 x 15?
OK, sappiamo che la risposta è 180 e ci sono molti metodi intuitivi che ci aiutano a ottenere la risposta giusta. Infatti 12 x 15 è solo un po 'più difficile da calcolare a 10 x 15, perché moltiplicando per 10' davvero facile - basta aggiungere uno 0 alla fine del numero. Così 15 x 10 è uguale a 150. Ma ora di nuovo il 12 x 15 - sappiamo che questo è uguale a 10 x 15 (che è 150) e 2 x 15, che è anche molto facile da calcolare ed è 30. Il risultato di 12 × 15 sarà di 150 + 30, che per fortuna non è difficile da ottenere e pari a 180.
E 'stato facile, ma in alcuni casi i calcoli sono un po' più difficile e abbiamo bisogno di un algoritmo strutturato per ottenere la risposta giusta. Che cosa circa 65 x 97? Non è così facile come 12 x 15, giusto?
L'algoritmo che conosciamo dalla scuola primaria, descritta nello schema qui sotto, è ben strutturato e ci aiutano a moltiplicare due numeri.
Moltiplicazione tipica

Vediamo che anche per i numeri a due cifre è molto difficile - ci sono 4 moltiplicazioni e alcune aggiunte.
Numero di moltiplicazioni
Abbiamo bisogno di 4 moltiplicazioni per calcolare il prodotto di due numeri a 2 cifre!
Tuttavia fino ad ora sappiamo come moltiplicare i numeri, l'unico problema è che il nostro compito diventa molto difficile in quanto i numeri crescono. Se moltiplicando 65 del 97 fosse in qualche modo facile, per quanto riguarda

1.374.773.294.776.321
2.x
3.222.384.759.707.982
Sembra quasi impossibile.

Storia

Andrey Kolmogorov è uno dei più brillanti matematici russi del 20 ° secolo. Nel 1960, durante un seminario, Kolmogorov ha dichiarato che due n-cifre non possono essere moltiplicate con meno di moltiplicazioni n2! 
Solo una settimana più tardi di 23 anni giovane studente chiamato Anatolii Alexeevitch Karatsubadimostrato che la moltiplicazione di due numeri di n cifre possono essere calcolati con n * lg (3) moltiplicazioni con un ingegnoso divide et impera approccio.

Panoramica

Fondamentalmente Karatsuba dichiarato che se abbiamo moltiplicare due cifre n-x ed y, questo può essere fatto con le seguenti operazioni, supponendo che B è la base e di m <n.
Prima sia x numeri e y può essere rappresentato come x1, x2 e y1, y2 con la seguente formulavisualizzare il cod
1.x = x1 * B ^ m + x2
2.y = y1 * B ^ m + y2
Ovviamente ora xy diventerà come il seguente prodotto.

1.xy = (x1 * B ^ m + x2) (y1 * B ^ m + y2) = & gt ;
2. 
3.a = x1 * y1
4.b = x1 * y2 + x2 * y1
5.c = x2 * y2
Infine xy diventerà:

1.xy = a * B ^ 2m + b * B ^ m + c
Tuttavia a, b, c possono essere calcolati con almeno quattro moltiplicazione, che non è un grande ottimizzazione. Questo è il motivo Karatsuba si avvicinò con la brillante idea di calcolare b con la seguente formula:

1.b = (x1 + x2) (y1 + y2) - a - c
Che fanno uso di soli tre moltiplicazioni per ottenere xy.
Vediamo questa formula con l'esempio.

01.47 x 78
02. 
03.x = 47
04.x = 4 * 10 + 7
05. 
06.x1 = 4
07.x2 = 7
08. 
09.y = 78
10.y = 7 * 10 + 8
11. 
12.y1 = 7
13.y2 = 8
14. 
15.a = x1 * y1 = 4 * 7 = 28
16.c = x2 * y2 = 7 * 8 = 56
17.b = (x1 + x2) (y1 + y2) - a - b = 11 * 15 - 28-56

Ora il fatto è che 11 * 15 è di nuovo una moltiplicazione tra i numeri a 2 cifre, ma per fortuna possiamo applicare le stesse regole due di loro. Questo rende l'algoritmo di Karatsuba un perfetto esempio l'algoritmo "divide et impera".

Implementazione

Moltiplicazione standard

In genere l'implementazione standard di moltiplicazione di n-cifre richiedono moltiplicazioni n2 come si può vedere dalla seguente PHP attuazione.

01.$ x = array (1,2,3,4);
02.$ y = array (5,6,7,8);
03. 
04.funzione multiply ($ x, $ y)
05.{  
06.$ len_x = count ($ x);
07.$ len_y = count ($ y);
08.$ half_x = ceil ($ len_x / 2);
09.$ half_y = ceil ($ len_y / 2);
10.$ base = 10;
11. 
12./ / inferiore della ricorsione
13.se ($ len_x == 1 && $ len_y == 1) {
14.tornare $ x [0] * $ y [0];
15.}
16. 
17.dollari x_chunks = array_chunk ($ x, $ half_x);
18.dollari y_chunks = array_chunk ($ y, $ half_y);
19. 
20./ / predefiniscono aliases
21.$ x1 = $ x_chunks [0];
22.$ x2 = $ x_chunks [1];
23.$ y1 = $ y_chunks [0];
24.$ y2 = $ y_chunks [1];
25. 
26.di ritorno   si moltiplicano ($ x1, $ y1) * pow ($ base, $ half_x * 2) / / a
27.+ (multiply ($ x1, $ y2) si moltiplicano + ($ x2, $ y1)) * pow ($ base, $ half_x) / / b
28.si moltiplicano + ($ x2, $ y2); / / c
29.}
30. 
31./ / 7 006 652
32.echo multiply ($ x, $ y);

Karatsuba Moltiplicazione

Karatsuba sostituisce due delle moltiplicazioni - questa di x1 * y2 + x2 * y1 con un solo - (x1 + x2) (y1 + y2) e questo rende più veloce l'algoritmo.

01.$ x = array (1,2,3,4);
02.$ y = array (5,6,7,8);
03. 
04.funzione karatsuba ($ x, $ y)
05.{
06.$ len_x = count ($ x);
07.$ len_y = count ($ y);
08. 
09./ / inferiore della ricorsione
10.se ($ len_x == 1 && $ len_y == 1) {
11.tornare $ x [0] * $ y [0];
12.}
13.se ($ len_x == 1 | | $ len_y == 1) {
14.$ t1 = implode ('', $ x);
15.$ t2 = implode ('', $ y);
16.return (int) $ t1 * $ t2;
17.}
18. 
19.$ a = array_chunk ($ x, ceil ($ len_x / 2));
20.$ b = array_chunk ($ y, ceil ($ len_y / 2));
21. 
22.° piano = $ ($ len_x / 2);
23. 
24.$ x1 = $ a [0]; / / 1
25.$ x2 = $ a [1]; / / 2
26.$ y1 = $ b [0]; / / 1
27.$ y2 = $ b [1]; / / 2
28. 
29.return   ($ a = karatsuba ($ x1, $ y1)) * pow (10, 2 * $ deg)
30.+ ($ c = karatsuba ($ x2, y2 $))
31.+ (karatsuba ( somma ($ x1, $ x2), sum ($ y1, $ y2)) - $ a - $ c) * pow (10, $ deg);
32.}
33. 
34./ / 7 006 652
35.echo karatsuba ($ x, $ y);

Complessità

Supponendo che sostituire due delle moltiplicazioni con un solo rende il programma più veloce. La domanda è quanto velocemente. Karatsuba migliora il processo di moltiplicazione sostituendo la complessità iniziale di O (n2) di O (nlg3), che come potete vedere nello schema qui sotto è molto più veloce per grandi n.
Karatsuba Complessità
O (n ^ 2) cresce molto più velocemente di O (n ^ LG3)

Applicazione

È ovvio in cui l'algoritmo Karatsuba può essere utilizzato. È molto efficace quando si tratta di moltiplicazione intera, ma che non è il suo unico vantaggio. E 'spesso usato per moltiplicazioni polinomiali.


Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.