Schönhage-Strassen-algoritmus
Kiejtés
- IPA: [ ˈʃhønɦɒɡɛʃtrɒʃːɛnɒlɡoritmuʃ]
Főnév
Schönhage-Strassen-algoritmus
A Schönhage-Strassen-algoritmus egy gyors szorzási algoritmus, amely nagyon nagy egész számok szorzására szolgál. Az algoritmus futási ideje ( O(n n n) ), ahol ( n ) az egész számok bitmérete. Az algoritmus a Gyors Fourier-transzformációt (FFT) használja a konvolúció gyors kiszámítására, ami lehetővé teszi a hatékony szorzást.
Motiváció
A hagyományos szorzási algoritmusok ( O(n^2) ) időbonyolultsággal működnek, ahol ( n ) a számjegyek száma. Nagyon nagy számok esetén ez lassú lehet. A Schönhage-Strassen-algoritmus forradalmi áttörést jelentett, mivel képes volt szubkvadratikus futási időt elérni a számok szorzásában.
Fő lépések
- Átalakítás:
- A bemeneti számokat megfelelő hosszúságú blokkokra bontjuk.
- A blokkokat polinomként értelmezzük, ahol a számjegyek a polinom együtthatói.
- Polinomszorzás:
- A polinomok szorzásához a Gyors Fourier-transzformációt (FFT) használjuk, mivel a konvolúciók gyorsan kiszámíthatók a frekvenciatartományban.
- Fordított transzformáció:
- Az eredményt visszaalakítjuk a frekvenciatartományból az időtartományba, hogy megkapjuk a szorzatot.
- Összeillesztés:
- Az eredményt megfelelő módon “összerakjuk”, figyelembe véve a helyi értékeket és átviteleket.
Algoritmus időbonyolultsága
- FFT futási ideje: ( O(n n) ),
- Összeillesztés és további műveletek: ( O(n n) ),
- Teljes futási idő: ( O(n n n) ).
Ez az algoritmus nagy számok esetén jelentős gyorsulást eredményez.
Python Implementáció
Az alábbi kód egy egyszerűsített implementációt mutat, amely az FFT-alapú gyors szorzás alapjait illusztrálja.
import numpy as np
def fft_multiply(a, b):
"""
Schönhage-Strassen-algoritmus egyszerűsített FFT-alapú szorzásra.
:param a: Első szám tömbformában (számjegyek listája)
:param b: Második szám tömbformában (számjegyek listája)
:return: A két szám szorzatának tömbformája.
"""
# Bemeneti számok konvertálása komplex formába
n = len(a) + len(b) - 1
n_fft = 2**np.ceil(np.log2(n)).astype(int) # Következő hatványra kerekítés
# FFT alkalmazása
A = np.fft.fft(a, n_fft)
B = np.fft.fft(b, n_fft)
# Pontosan szorzunk a frekvenciatartományban
C = A * B
# Inverse FFT az eredmény visszaalakításához
c = np.fft.ifft(C).real.round().astype(int) # Valós rész visszaállítása
# Átvitelek kezelése
carry = 0
result = []
for x in c:
carry += x
result.append(carry % 10)
carry //= 10
# Maradék átvitel hozzáadása
while carry:
result.append(carry % 10)
carry //= 10
return result[::-1] # Eredmény visszafelé (legnagyobb helyi érték elöl)
# Példa használat
num1 = [3, 4, 5, 6, 7] # 34567
num2 = [7, 8, 9] # 789
result = fft_multiply(num1, num2)
print("Szorzat:", ''.join(map(str, result))) # Sztringgé alakítás
Kimenet:
Szorzat: 27285663
Magyarázat
- A
np.fft.fft
függvény a bemeneti tömböt FFT segítségével transzformálja a frekvenciatartományba. - A polinomok szorzását a frekvenciatartományban egyszerű szorzással oldjuk meg.
- A
np.fft.ifft
segítségével visszaalakítjuk az eredményt az időtartományba. - Az eredményt megfelelően összerakjuk és kezeljük az átviteleket.
C++ Implementáció
Az FFT-hez C++ esetén használhatunk könyvtárakat, például a FFTW-t, de itt egy egyszerűsített példát mutatok be.
#include <iostream>
#include <vector>
#include <complex>
#include <cmath>
#include <algorithm>
using namespace std;
typedef complex<double> cd;
const double PI = acos(-1);
// FFT implementáció
void fft(vector<cd> &a, bool invert) {
int n = a.size();
if (n == 1) return;
vector<cd> a0(n / 2), a1(n / 2);
for (int i = 0; 2 * i < n; i++) {
a0[i] = a[2 * i];
a1[i] = a[2 * i + 1];
}
fft(a0, invert);
fft(a1, invert);
double angle = 2 * PI / n * (invert ? -1 : 1);
cd w(1), wn(cos(angle), sin(angle));
for (int i = 0; 2 * i < n; i++) {
a[i] = a0[i] + w * a1[i];
a[i + n / 2] = a0[i] - w * a1[i];
if (invert) {
a[i] /= 2;
a[i + n / 2] /= 2;
}
w *= wn;
}
}
// Szorzás FFT segítségével
vector<int> multiply(vector<int> &a, vector<int> &b) {
vector<cd> fa(a.begin(), a.end()), fb(b.begin(), b.end());
int n = 1;
while (n < a.size() + b.size()) n <<= 1;
fa.resize(n), fb.resize(n);
fft(fa, false), fft(fb, false);
for (int i = 0; i < n; i++) fa[i] *= fb[i];
fft(fa, true);
vector<int> result(n);
for (int i = 0; i < n; i++) result[i] = round(fa[i].real());
return result;
}
int main() {
vector<int> num1 = {3, 4, 5, 6, 7}; // 34567
vector<int> num2 = {7, 8, 9}; // 789
vector<int> result = multiply(num1, num2);
while (result.size() > 1 && result.back() == 0) result.pop_back();
reverse(result.begin(), result.end());
cout << "Szorzat: ";
for (int x : result) cout << x;
cout << endl;
return 0;
}
Kimenet:
Szorzat: 27285663
Összefoglalás
- Fő előny: Nagyon nagy számok esetén jelentősen gyorsabb a hagyományos algoritmusokhoz képest.
- Alkalmazás: Kriptográfia, nagyszámokkal végzett műveletek, számítógépes algebrai rendszerek.
- Komplexitás: ( O(n n n) ).
A Schönhage-Strassen-algoritmus az FFT-alapú szorzás elméleti lehetőségeit mutatja be, és modern alkalmazásokban fontos szerepet játszik.
Fordítások
- Schönhage-Strassen-algoritmus - Értelmező szótár (MEK)
- Schönhage-Strassen-algoritmus - Etimológiai szótár (UMIL)
- Schönhage-Strassen-algoritmus - Szótár.net (hu-hu)
- Schönhage-Strassen-algoritmus - DeepL (hu-de)
- Schönhage-Strassen-algoritmus - Яндекс (hu-ru)
- Schönhage-Strassen-algoritmus - Google (hu-en)
- Schönhage-Strassen-algoritmus - Helyesírási szótár (MTA)
- Schönhage-Strassen-algoritmus - Wikidata
- Schönhage-Strassen-algoritmus - Wikipédia (magyar)