Algoritmus Karatsuba - Karatsuba algorithm

The Algoritmus Karatsuba je rychlý multiplikační algoritmus. Objevil jej Anatoly Karatsuba v roce 1960 a publikován v roce 1962.[1][2][3] Snižuje násobení dvou n-místná čísla maximálně jednociferné násobení obecně (a přesně když n je síla 2). Je tedy rychlejší než tradiční algoritmus, který vyžaduje jednociferné produkty. Například algoritmus Karatsuba vyžaduje 310 = 59 049 jednociferných násobení k vynásobení dvou 1024-místných čísel (n = 1024 = 210), zatímco tradiční algoritmus vyžaduje (210)2 = 1 048 576 (zrychlení 17,75krát).
Algoritmus Karatsuba byl prvním multiplikačním algoritmem asymptoticky rychlejším než kvadratický algoritmus „základní školy“. Algoritmus Toom – Cook (1963) je rychlejší zobecnění Karatsubovy metody a Schönhage – Strassenův algoritmus (1971) je pro rychlejší ještě rychlejší n.
Dějiny
Standardní postup pro násobení dvou n-místná čísla vyžadují několik základních operací úměrných nebo v big-O notace. Andrey Kolmogorov domníval se, že tradiční algoritmus byl asymptoticky optimální, což znamená, že jakýkoli algoritmus pro tento úkol by vyžadoval základní operace.
V roce 1960 uspořádal Kolmogorov v Matematice seminář o matematických problémech kybernetika na Moskevská státní univerzita, kde uvedl domněnky a další problémy v EU složitost výpočtu. Během týdne našel Karatsuba, 23letý student, algoritmus (později nazvaný „rozděl a panuj“), který znásobí dva n-místná čísla v základní kroky, čímž vyvrací domněnku. Kolmogorov byl z objevu velmi nadšený; sdělil to na příští schůzi semináře, která byla poté ukončena. Kolmogorov přednesl několik přednášek o výsledku Karatsuba na konferencích po celém světě (viz například „Proceedings of the International Congress of Mathematicians 1962“, s. 351–356 a také „6 přednášek přednesených na Mezinárodním kongresu matematiků v Stockholm, 1962 “) a tuto metodu publikoval v roce 1962, v Sborník Akademie věd SSSR. Článek napsal Kolmogorov a obsahoval dva výsledky násobení, Karatsubův algoritmus a samostatný výsledek Jurij Ofman; uvádí jako autory „A. Karatsuba a Yu. Ofman“. Karatsuba se o papíru dozvěděl až poté, co obdržel dotisky od vydavatele.[2]
Algoritmus
Základní krok
Základním krokem Karatsubova algoritmu je vzorec, který umožňuje vypočítat součin dvou velkých čísel a pomocí tří násobení menších čísel, každé s přibližně polovinou tolik číslic jako nebo , plus několik dodatků a posunů číslic. Tento základní krok je ve skutečnosti zobecněním podobný komplexní multiplikační algoritmus, Kde imaginární jednotka i je nahrazen výkonem základna.
Nechat a být reprezentován jako -místné řetězce v nějaké základně . Pro jakékoli kladné celé číslo méně než , lze napsat dvě zadaná čísla jako
kde a jsou menší než . Produkt je tedy
kde
Tyto vzorce vyžadují čtyři násobení a byly známy Charles Babbage.[4] Karatsuba to poznamenal lze vypočítat pouze ve třech násobeních, za cenu několika přídavků navíc. S a jako dříve je to možné pozorovat
Problém, ke kterému však dochází při práci s počítačem je, že výše uvedený výpočet a může vést k přetečení (způsobí výsledek v rozsahu ), které vyžadují multiplikátor s jedním bitem navíc. Tomu lze zabránit tím, že si to všimneme
Tento výpočet a vytvoří výsledek v rozsahu . Tato metoda může vytvářet záporná čísla, která vyžadují jeden bit navíc pro zakódování signality, a přesto by pro multiplikátor vyžadovala jeden bit navíc. Jedním ze způsobů, jak tomu zabránit, je zaznamenat znaménko a poté použít absolutní hodnotu a provést nepodepsané násobení, po kterém může být výsledek negován, když se oba znaky původně lišily. Další výhodou je, že i když může být záporný, konečný výpočet zahrnuje pouze doplňky.
Příklad
Chcete-li vypočítat součin čísel 12345 a 6789, kde B = 10, vyberte m = 3. Používáme m posuny doprava pro rozložení vstupních operandů pomocí výsledné základny (Bm = 1000), tak jako:
- 12345 = 12 · 1000 + 345
- 6789 = 6 · 1000 + 789
Pouze tři násobení, která fungují na menších celých číslech, se používají k výpočtu tří dílčích výsledků:
- z2 = 12 × 6 = 72
- z0 = 345 × 789 = 272205
- z1 = (12 + 345) × (6 + 789) − z2 − z0 = 357 × 795 − 72 − 272205 = 283815 − 72 − 272205 = 11538
Výsledek získáme pouhým přidáním těchto tří dílčích výsledků, odpovídajícím způsobem posunutých (a poté vezmeme v úvahu přenesení těchto tří vstupů v základně 1000 jako pro vstupní operandy):
- výsledek = z2 · (Bm)2 + z1 · (Bm)1 + z0 · (Bm)0, tj.
- výsledek = 72 · 10002 + 11538 · 1000 + 272205 = 83810205.
Všimněte si, že mezilehlé třetí multiplikace pracuje na vstupní doméně, která je méně než dvakrát větší než u dvou prvních multiplikací, její výstupní doména je méně než čtyřikrát větší a base-1000 nese vypočítané z prvních dvou násobení je třeba vzít v úvahu při výpočtu těchto dvou odčítání.
Rekurzivní aplikace
Li n je čtyři nebo více, tři násobení v základním kroku Karatsuby zahrnují operandy s méně než n číslice. Proto lze tyto produkty vypočítat pomocí rekurzivní volání algoritmu Karatsuba. Rekurzi lze použít, dokud nejsou čísla tak malá, že je lze (nebo musí) vypočítat přímo.
V počítači s plným 32bitovým na 32bitovým násobitel dalo by se například vybrat B = 231 = 2147483648a každou číslici uložte jako samostatné 32bitové binární slovo. Pak částky X1 + X0 a y1 + y0 nebude potřebovat další binární slovo pro uložení číslice přenosu (jako v carry-save zmije ) a lze použít rekurzi Karatsuba, dokud nejsou násobící čísla dlouhá pouze jedna číslice.
Asymetrické vzorce podobné Karatsubě
Karatsubův původní vzorec a další zevšeobecnění jsou samy o sobě symetrické. Například vypočítá následující vzorec
se 6 násobeními v , kde je pole Galois se dvěma prvky 0 a 1.
kde a .Upozorňujeme, že sčítání a odčítání je v polích charakteristiky 2 stejné.
Tento vzorec je symetrický, konkrétně se nezmění, pokud vyměníme a v a .
Na základě druhého Zobecněné algoritmy dělení,[5] Fan et al. našel následující asymetrický vzorec:
kde a .
Je to asymetrické, protože následující nový vzorec můžeme získat výměnou a v a .
kde a .
Analýza účinnosti
Základní krok Karatsuby funguje pro jakoukoli základnu B a jakékoli m, ale rekurzivní algoritmus je nejúčinnější, když m je rovný n/ 2, zaokrouhleno nahoru. Zejména pokud n je 2k, pro celé číslo ka rekurze se zastaví, pouze když n je 1, pak je počet jednociferných násobení 3k, který je nC kde C = log23.
Jelikož lze rozšířit libovolné vstupy s nulovými číslicemi, dokud jejich délka není síla dvou, vyplývá z toho, že počet elementárních násobení pro libovolné n, je nanejvýš .
Od sčítání, odčítání a posunutí číslic (násobení mocninami B) v základním kroku Karatsuby trvá čas úměrný n, jejich náklady se stanou zanedbatelnými, protože n zvyšuje. Přesněji řečeno, pokud t(n) označuje celkový počet základních operací, které algoritmus provádí při vynásobení dvou n- tedy číslice
pro některé konstanty C a d. Pro tohle relace opakování, hlavní věta o dělení a dobývání opakování dává asymptotické vázaný .
Z toho vyplývá, že pro dostatečně velké n, Karatsubův algoritmus provede méně posunů a jednociferných sčítání než longhandové násobení, i když jeho základní krok používá více sčítání a posunů než přímý vzorec. Pro malé hodnoty n, operace navíc posunu a přidání však mohou způsobit, že běží pomaleji než metoda longhand. Bod pozitivního výnosu závisí na počítačová platforma a kontext. Pravidlem je, že Karatsubova metoda je obvykle rychlejší, když jsou multiplikátory delší než 320–640 bitů.[6]
Pseudo kód
Zde je pseudokód pro tento algoritmus, který používá čísla představovaná v základní desítce. Pro binární reprezentaci celých čísel stačí nahradit všude 10 čísly 2.[7]
Druhý argument funkce split_at určuje počet číslic, které se mají extrahovat z že jo: například split_at ("12345", 3) extrahuje 3 poslední číslice, přičemž dává: high = "12", low = "345".
postup karatsuba(num1, num2) -li (num1 < 10) nebo (num2 < 10) vrátit se num1 × num2 / * Vypočítá velikost čísel. * / m = min(size_base10(num1), size_base10(num2)) m2 = podlaha(m / 2) / * m2 = strop (m / 2) bude také fungovat * / / * Rozdělte sekvence číslic doprostřed. * / vysoký1, low1 = split_at(num1, m2) vysoký2, low2 = split_at(num2, m2) / * 3 hovory na čísla přibližně poloviční velikosti. * / z0 = karatsuba(low1, low2) z1 = karatsuba((low1 + vysoký1), (low2 + vysoký2)) z2 = karatsuba(vysoký1, vysoký2) vrátit se (z2 × 10 ^ (m2 × 2)) + ((z1 - z2 - z0) × 10 ^ m2) + z0
Reference
- ^ A. Karatsuba a Yu. Ofman (1962). "Násobení mnoha digitálních čísel automatickými počítači". Sborník Akademie věd SSSR. 145: 293–294. Překlad v akademickém časopise Fyzika-Doklady, 7 (1963), str. 595–596
- ^ A b A. A. Karatsuba (1995). „Složitost výpočtů“ (PDF). Sborník Steklovova matematického ústavu. 211: 169–183. Překlad od Trudy Mat. Inst. Steklova, 211, 186–202 (1995)
- ^ Knuth D.E. (1969) Umění počítačového programování. v.2. Addison-Wesley Publ.Co., 724 stran.
- ^ Charles Babbage, kapitola VIII - Analytického motoru, ošetřeno větší počty, Úryvky ze života filozofa, Longman Green, Londýn, 1864; strana 125.
- ^ Haining Fan, Ming Gu, Jiaguang Sun, Kwok-Yan Lam, „Získání více vzorců podobných karatsubě přes binární pole“, IET Information security Vol. 6 č. 1, s. 14-19, 2012.
- ^ "Násobení Karatsuba". www.cburch.com.
- ^ Weiss, Mark A. (2005). Datové struktury a analýza algoritmů v C ++. Addison-Wesley. p. 480. ISBN 0321375319.
externí odkazy
- Karatsubův algoritmus pro polynomiální násobení
- Weisstein, Eric W. "Násobení Karatsuba". MathWorld.
- Bernstein, D. J., "Multiidigitální násobení pro matematiky Pokrývá Karatsuba a mnoho dalších multiplikačních algoritmů.