Szybkie potęgowanie - ilość mnożeń

0

Hej, mam taki algorytm szybkiego potęgowania, znajoma jest mi już idea jego działania, proszę tylko o pomoc w policzeniu liczby mnożeń.

Mianowicie załóżmy dwa przypadki (x to liczba, n to wykładnik)

  • x=2 n=134
  • x=2 n=8

Czy w tym algorytmie zakładamy że wiemy ile to jest 267 i 24? Bo jeśli tak to robimy jedno mnożenie podnosząc te liczby do kwadratu i koniec. Jeśli natomiast nie to liczba mnożeń wynosi 67 i 4 aby uzyskać dane liczby, zgadza się? w tradycyjnym algorytmie ilość mnożeń jest równa n-1. Jeśli coś źle myślę to proszę o wyprowadzenie z błędu i pomoc w zrozumieniu liczenia mnożeń jakie wykonuje ten algorytm.

potęga(x,n)
if n=0
   then return 1;
if n!%=0
return x*(potęga(x,(n-1)/2)^2
else return (potęga(x,n/2))^2
 
0

sory za refresh ale jutro o 8 rano mam egzamin z algorytmów i bardzo proszę o pomoc w zliczeniu tych mnożeń

przykład

załóżmy że chcemy pomnożyć tym algorytmem 2187. licząc naiwnie wykonujemy 186 mnożeń (bo n-1 gdzie n to wykładnik). wykorzystując jednak algorytm szybkiego potęgowania 2187 zapisujemy jako 293 - wykonujemy 92 mnożenia. Teraz 293 podnosimy do kwadratu uzyskując 2186 - czyli wykonaliśmy dodatkowe jedno mnożenie, i do tego mnożymy jeszcze 2186 * 2 żeby uzyskać 2187 co dodaje nam jeszcze jedno mnożenie.

podsumowując - naiwnie mamy 186 mnożen, a korzystając z algorytmu mamy 94 mnożenia. Dobrze kombinuję ?

0

Dobrze, ilość operacji mnożenia to n/2 + 1

Edit: maksymalnie n/2 + 1

1

Ani trochę bo przecież tego 293 też nie mnozysz naiwnie tylko połówkując...

0

To znaczy mam połówkować aż do momentu gdy dalej nie będzie się dało tego rozłożyć?

Shalom mozesz to rozpisać jak to zrobić na przykładzie ? :D

1

No przecież chyba widzisz algorytm napisany w pierwszym poście o_O
Wyliczenie an wymaga:

  • policzenia x = a(n/2)
  • pomnożenia x*x
    A wyliczenie a(n/2) ? Analogicznie:
  • policzenia x = a(n/4)
  • pomnożenia x*x
    i tak dalej...
0

Czyli np a86 = a43 * a43 = (a21 * a21 * a) 2 itd ... i tak aż dostane we wzorze same a2? Bo jeśli tak to jest to bardzo żmudne i rozpisanie np a187 zajęłoby bardzo dużo czasu, aż za dużo, jak na jeden podpunkt na egzaminie ...

1

Żeby policzyć ile mnożeń będzie potrzebne nie trzeba tego rozpisywać, wystarczy użyć mózgu ;] Ale rozpisz sobie trochę przykładów i może dojdziesz do jakiejś zależności. Zalecam jednak rozpisywać to na zasadzie
a187 = a43 * a43 * a -> dwa mnożenia
a43 = a21 * a21 * a -> dwa mnożenia
a21 = a10 * a10 * a -> dwa mnożenia
a10 = a5 * a5 -> jedno mnożenie
a5 = a2 * a2 * a -> dwa mnożenia
a2 = a*a -> jedno mnożenie
w sumie 2+2+2+1+2+1 = 10, chyba trochę lepiej niż twoje 94 mnożenia które proponowałeś wyżej :D
Co więcej zajęło mi to "żmudne rozpisanie" całą minutę...

0
Shalom napisał(a):

a187 = a43 * a43 -> jedno mnożenie

@Shalmon popraw

0

@Shalom jednak mnożen jest więcej.

Zauważ że np

a187 = a43 * a43 * a -> dwa mnożenia
a43 = a21 * a21 * a -> ????dwa mnożenia???? --> sugerujesz że na tym etapie są cztery mnożenia, a czy jednak nie ma ich więcej?

czyli a187 = (a21 * a21 * a) * (a21 * a21 * a) * a . -- > 6 mnożeń, a nie 4 .

1

No jak ktoś jest idiotą i chce dwa razy wyliczać coś co już zna to jasne. Jak policzyłeś sobie raz a43 to PO CO chcesz je liczyć drugi raz? o_O Mijasz się chyba z powołaniem na tej informatyce...

0

A ty konkretnie w jakim celu robisz te przytyki ? Masz jakiś kłopot ze sobą ? To już nie pierwszy raz, więc może czas wyjść z domu przed komputerka do ludzi, bo niedługo stuknie 18 tysięcy postów, zastanów się nad tym.

1

A ty konkretnie w jakim celu robisz te przytyki

Bo mam dobre serce i chcę cię uratować przed zmarnowaniem kilku lat na studiowanie czegoś co ci się w życiu nie przyda...

0

Haha właśnie takiej motywacji potrzebowałem w noc zarywaną przed egzaminem :D Potęgowanie opanowane - temat do zamknięcia.

1

Zawsze do usług :) Powodzenia na egzaminie. Może jakimś cudem nie pojawi się zadanie w którym trzeba będzie coś wymyślić, bo może być ciężko ;]

0

Jak udowodnić że szybkie potęgowanie przy dzieleniu wykładnika przez 3 a nie przez 2 będzie wymagało mniejszej liczby mnożeń?

Chodzi mi o to że jak zwieszamy liczbę przez którą dzielimy to maleje liczba potrzebnych iteracji ale rośnie liczba mnożeń na iteracje i chodzi mi o to jak policzyć(analitycznie) dla jakiego dzielnika wyjdzie najlepszą wydajność. Numerycznie sprawdziłem i wychodzi że 4.
To jest ten sam problem jak znalezienie takiej podstawy reprezentacji liczb która zabiera jak najmniej pamięci. Rozwiązaniem tego problemu jest liczba e - najbliższa naturalna to 3. Tylko nie wiem jak to policzyć :C

0

Przy okzaji @Shalom - zdałem, dokładnie ten algorytm się pojawił i wpadł MAX także dzięki za pomoc jeszcze raz, jednak kto nie pyta ten błądzi.

A co do pytania topik92, jak już wcześniej udowodniłem to geniuszem nie jestem ale czy aby na pewno uzyskasz mniejszą złożoność obliczeniową algorytmu dla większego dzielnika?

Biorąc dla przykładu liczbę a187 i rozkładając wykładnik poprzez dzielenie go przez 2 - wyszło nam 10 mnożeń. Jeśli będziemy dzielić wykładnik przez 3 to :

a187= a62 * a62 * a62 * a ->3 mnożenia
a62=a20*a20*a20a2 -> 3 mnożenia + a2=aa
i tutaj musimy rozpisać nie tylko a20 ale także a2 więc już widać, że ilość mnożeń będzie większa. Chyba właśnie na tym polega sukces dzielenia wykładnika przez 2, że reszta z dzielenia zawsze jest 0 lub 1. Wgl jak wpadłeś na to że dla exponenty jest to wydajniejsze ? Może indukcji matematycznej trzeba spróbować, w końcu to liczby naturalne.

Mogę się mylić. Najpewniej się mylę.

1

@topik92 dowód może być analityczny i opierać się będzie o takie magiczne pojęcie jak logarytm. Bo właśnie logarytm potrafi powiedzieć ci ile tych mniejszych czynników będziesz miał.
Załóżmy przypadek prosty kiedy wszystko jest potęgą 2, żeby się ładnie liczyło:
a64 = a32 * a32
a32 = a16 * a16
a16 = a8 * a8
a8 = a4 * a4
a4 = a2 * a2
a2 = a * a

Więc do policzenia mamy: a2, a4, a8, a16 i a32 czyli 5 wyrazów podczas gdy log2(64) = 6
Nie jest to przypadek ;)
W przypadku ogólnym dla każdego czynnika możemy wykonać 1 lub 2 mnożenia, zależnie od tego czy był podzielny przez 2 nie. Jeśli wszystkie są podzielne to liczba potrzebnych mnożeń wyniesie po prostu log2(exponenta)-1, jeśli mamy przypadek pesymistyczny to na każdym poziomie będą potrzebne 2 mnożenia, czyli w sumie 2*(ceil(log2(exponenta))-1). Czy faktycznie tak jest? Weźmy na przykład a63 i rozpiszmy tak jak poprzednio:

a63 = a31 * a31 * a
a31 = a15 * a15 * a
a15 = a7 * a7 * a
a7 = a3 * a3 * a
a3 = a * a * a

Jak widać mamy tutaj 5*2 = 10 mnożeń, podczas gdy log2(63) = 5.97 i jednocześnie ceil(5.97) = 6 więc 2*(ceil(log2(exponenta))-1) = 2*(6-1) = 10

Średnio dla losowej liczby będziemy potrzebowali w połowie przypadków 2 mnożeń i w połowie 1 mnożenia, więc średnio *1.5 ale jeśli interesuje nas tylko rząd zlożoności to mamy po prostu O(log(exponenta)).

Co się zmieni jeśli zmienimy dzielnik z 2 na 3? Zmieni sie podstawa logarytmu oraz liczba mnożeń potrzebnych w jednej rundzie - tym razem będą potrzebne 2 lub 3 mnożenia. Optymistycznie będzie więc (log3(exponenta)-1)*2 a pesymistycznie (log3(exponenta)-1)*3, a średnio oczywiście *2.5 i jednocześnie rząd złożoności to O(log3(exponenta)).

Pytanie więc czy (dla przypadku średniego) funkcja (log2(n)-1)*1.5 rośnie szybciej czy wolniej od (log3(n)-1)*2.5. Polecam czytelnikowi przeprowadzić analizę obu tych funkcji w celu ustalenia stanu faktycznego, podpowiem jednak że wynikiem powinien być wniosek, że dla odpowiednio dużych n funkcja z 3 rośnie szybciej.

0

zrobiłem czeski błąd i dla 3 i zamiast rozkładać x62 na :
x20 * x20 * x20 * x *x
rozkładałem na x20 * x20 *x *x
pomijając że to jest bez sensu to w takim przypadku dla 3 i 62 wychodzi
log3(62)+log3(62)*średnia_ilość_mnożeń
średnia_ilość_mnożeń - można zastąpić zapiać ze wzoru na sumę szeregu arytmetycznego od 0 do 2 przez ilość elementów - i po skróceniu wychodzi cos takiego
log3(62)+log3(62)* (3-1)/2
jesli podstawimy za 62-n a za dzielnik d dla d > 1;

log_podstawa_d(n)+log-podstawa-d(n)*  (d-1)/2 =>
log_podstawa_d (n) (1 + (d-1)/2) =>
ln(n)/ln(d) * (1 + (d-1)/2)

co już takie trywialne i intuicyjne nie jest,
nie mogłem do tego dojść bo robiłem nie to co trzeba i cały czas się coś nie zgadzało :P.

1 użytkowników online, w tym zalogowanych: 0, gości: 1