Tutaj uczymy się pomysłowego zastosowania algorytmu dziel i zwyciężaj w połączeniu z algebrą liniową do mnożenia dużych liczb, szybko. Oraz wprowadzenie do notacji Big-O!
W rzeczywistości ten wynik jest tak sprzeczny z intuicją, że wielki matematyk Kołmogorow przypuszczał, że tak szybki algorytm nie istnieje.
Part 0: Long Multiplication is Slow Multiplication. (I wprowadzenie do notacji Big-O)
Wszyscy pamiętamy naukę mnożenia w szkole. W rzeczywistości, muszę się do tego przyznać. Pamiętajcie, to jest strefa bez oceniania 😉
W szkole mieliśmy 'mokrą zabawę’, kiedy deszcz padał zbyt mocno, aby bawić się na placu zabaw. Podczas gdy inne (normalne/lubiące zabawę/pozytywny przymiotnik do wyboru) dzieci grały w gry i wygłupiały się, ja czasami brałem kartkę papieru i mnożyłem razem duże liczby, tak dla samej przyjemności. Czysta radość z obliczeń! Mieliśmy nawet konkurs mnożenia, „Super 144”, w którym musieliśmy pomnożyć zakodowaną siatkę 12 na 12 liczb (od 1 do 12) w jak najkrótszym czasie. Ćwiczyłem to religijnie, do tego stopnia, że miałem swoje własne przygotowane arkusze ćwiczeniowe, które kserowałem, a następnie używałem na zmianę. W końcu osiągnąłem czas 2 minut i 1 sekundy, przy którym mój fizyczny limit bazgrania został osiągnięty.
Mimo tej obsesji na punkcie mnożenia, nigdy nie przyszło mi do głowy, że moglibyśmy to robić lepiej. Spędziłem tak wiele godzin na mnożeniu, ale nigdy nie próbowałem ulepszyć algorytmu.
Rozważmy mnożenie 103 przez 222.
Obliczamy 2 razy 3 razy 1 +2 razy 0 razy 10 + 2 razy 1 razy 100 + 20 razy 3 razy 1 + 20 razy 0 razy 10 + 20 razy 1 razy 100 = 22800
Ogólnie, aby pomnożyć n cyfr, potrzeba O(n²) operacji. Notacja 'big-O’ oznacza, że gdybyśmy mieli wykreślić wykres liczby operacji jako funkcji n, termin n² jest naprawdę tym, co się liczy. Kształt jest zasadniczo kwadratowy.
Dzisiaj spełnimy wszystkie nasze dziecięce marzenia i udoskonalimy ten algorytm. Ale najpierw! Czeka nas Big-O.
Big-O
Spójrz na dwa wykresy poniżej
Zapytaj matematyka, „czy x² i x²+x^(1/3) są takie same?”, a prawdopodobnie zwymiotuje do swojej filiżanki z kawą, zacznie płakać i mamrotać coś o topologii. Przynajmniej taka była moja reakcja (na początku), a ja prawie nic nie wiem o topologii.
Ok. To nie jest to samo. Ale nasz komputer nie dba o topologię. Komputery różnią się wydajnością na tak wiele sposobów, których nawet nie potrafię opisać, bo nic nie wiem o komputerach.
Ale nie ma sensu dostrajać walca parowego. Jeśli dwie funkcje, dla dużych wartości ich danych wejściowych, rosną w tym samym rzędzie wielkości, to dla celów praktycznych zawiera to większość istotnych informacji.
Na powyższym wykresie widzimy, że te dwie funkcje wyglądają dość podobnie dla dużych danych wejściowych. Ale podobnie, x² i 2x² są podobne – ta druga jest tylko dwa razy większa od pierwszej. Przy x = 100, jeden jest 10 000, a drugi 20 000. Oznacza to, że jeśli możemy obliczyć jedną, prawdopodobnie możemy obliczyć drugą. Natomiast funkcja, która rośnie wykładniczo, powiedzmy 10^x, przy x = 100 jest już o wiele większa niż liczba atomów we wszechświecie. (10¹⁰⁰ >>>> 10⁸⁰, co jest szacunkową liczbą Eddingtona na temat liczby atomów we wszechświecie według mojego Googlowania*).
*prawdę mówiąc, użyłem DuckDuckGo.
Pisanie liczb całkowitych jako wielomianów jest zarówno bardzo naturalne, jak i bardzo nienaturalne. Napisanie 1342 = 1000 + 300 + 40 + 2 jest bardzo naturalne. Zapisanie 1342 = x³+3x²+4x + 2, gdzie x = 10, jest nieco dziwne.
W ogólności, załóżmy, że chcemy pomnożyć dwie duże liczby, zapisane w podstawie b, o n cyfrach każda. Każdą n-cyfrową liczbę zapisujemy jako wielomian. Jeśli podzielimy liczbę n-cyfrową na r części, to wielomian ten ma n/r wyrazów.
Na przykład, niech b = 10, r = 3, a nasza liczba to 142,122,912