![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 380 Pomógł: 59 Dołączył: 24.04.2010 Skąd: London Ostrzeżenie: (0%) ![]() ![]() |
Witajcie mój problem brzmi następująco mam do napisania klase która w sposób rekurencyjny ma realizować potęgowanie i taką napisałem,
kolejną rzeczą jest to że obiekt tej klasy ma buforować wyniki i wykorzystać bufor zamiast wykonywania metody co przez to rozumiecie? Ten post edytował lord2105 17.08.2010, 17:07:35 -------------------- |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 812 Pomógł: 117 Dołączył: 2.12.2008 Ostrzeżenie: (10%) ![]() ![]() |
To, że jeśli podnosisz np. N ^ 10, to można to rozpisać tak:
N ^ 10 = N ^ 8 * N ^ 2; N ^ 8 = N ^ 4 * N ^ 4; N ^ 4 = N ^ 2 * N ^ 2; N ^ 2 = N ^ 1 * N ^ 1; N ^ 1 = N; Dzięki buforowaniu pośrednich operacji, zamiast wykonać 10 mnożeń, możesz wykonać ich tylko 4 w tym przypadku, ale przy większych liczbach korzyści są znacznie większe bo rosną funkcją potęgową. -------------------- |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) ![]() ![]() |
Przekazuj w parametrze funkcji tablicę zawierająca wyniki poprzednich mnożeń - każde wywołanie dodaje nowy rezultat do tablicy - pod koniec powinieneś otrzymać tablicę z wynikami potęgi począwszy od 1 - zapamiętujesz ją we właściwości metody jako podtablicę z kluczem będącym twoją liczbą.
Przy kolejnych wywołaniach sprawdzasz czy dla danej liczby nie istnieje już tablica, jeśli tak to sprawdzasz czy zawiera wartość którą chcesz obliczyć - zwracasz ją. W przeciwnym wypadku bierzesz ostatnią wartość tablicy - powiedzmy w tablicy masz potęgę 3 liczby 2, ty szukasz potęgi 6 liczby 2 - zamiast stosować rekurencję od potęgi 1, stosujesz od 3 bo masz obliczoną jej wartość. Pisane na szybko więc nie daję głowy że jest ok (przy moim pokrętnym rozumieniu matematyki zdziwiłbym się gdyby było). -------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 380 Pomógł: 59 Dołączył: 24.04.2010 Skąd: London Ostrzeżenie: (0%) ![]() ![]() |
Po części chwyciłem o co Wam chodzi lecz bufor powinien występować bezpośrednio w klasie czy też przy wywoływaniu obiektu, pokaże co do tej pory napisałem w pliku class.calculate.php:
czy da sie zastosować bufor w tej klasie? Czy też jest on zbędny? i show.php
Ten post edytował lord2105 17.08.2010, 17:43:57 -------------------- |
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarejestrowani Postów: 812 Pomógł: 117 Dołączył: 2.12.2008 Ostrzeżenie: (10%) ![]() ![]() |
[...] lecz bufor powinien występować bezpośrednio w klasie czy też przy wywoływaniu obiektu [...] Lepiej bezpośrednio w klasie, ponieważ wtedy, przy kolejnych obliczeniach, klasa już będzie miała wykonaną część obliczeń. -------------------- |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) ![]() ![]() |
@lord105 - nie wywołuj rekurencyjnie w metodzie tworzenia nowego obiektu. To kompletnie bez sensu. Wywołuj samą metodę tego samego obiektu np.
@flashdev - na upartego to można cache zadeklarować jako właściwość statyczną - wtedy wszystkie obiekty będą operowały na jednym. Unikamy dzięki temu zbędnej redundancji. -------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
![]()
Post
#7
|
|
![]() Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Flashdev: Twoja metoda jest dobra dla dużych potęg, jednak dla niższych niekoniecznie. Zwróć uwagę na konieczność sprawdzania czy dana potęga już aby nie wystąpiła w trakcie obliczeń. Jak chcesz rozwiązać ten akurat problem? Deklarowanie tablicy wyników potęg typu przykładowo dla 5 array( 1 => 5, 2 => 25, 4 => 625, 8 => 390625) a potem sprawdzając czy mnożenie potęgi aktualnej * 2 jest większe od wymaganej? Jeśli tak wykonaj operację, dodaj do tablicy potęg i rób dalej rekurencję. Jeśli nie leć dodaj bezpośrednio niższą potęgę i sprawdź czy większa od wymaganej. Jeśli nie dodaj potęgę a wynik pomnóż przez odpowiadającą mu wartość. I tak aż do osiągnięcia właściwej potęgi. Trochę zagmatwanie napisałem, ale chyba rozumiesz o co chodzi.
Jednym zdaniem: "Dla względnie małych potęg naddatek operacji sprawdzających odbije się negatywnie na wydajności i ta rekurencja puszczona wprost na koprocesor wykona się znacznie szybciej, bo ma on dedykowane rejestry do tego typu zadań." -------------------- Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
|
|
|
![]()
Post
#8
|
|
![]() Grupa: Zarejestrowani Postów: 812 Pomógł: 117 Dołączył: 2.12.2008 Ostrzeżenie: (10%) ![]() ![]() |
Specjalnie nie podałem gotowego algorytmu, żeby zmusić czytelnika do myślenia. Ale widzę, że nie znając jeszcze tego prostego algorytmu już udało Ci się wykonać jego analizę wydajnościową ![]() Poniżej przedstawiam mój (no bez przesady, jaki tam mój... ja nie wymyślam na poczekaniu takich mądrych rzeczy) algorytm. Kod // zadanie: a ^ b // Przeliczamy b na system binarny. A tak naprawdę to nie przeliczamy, bo ona już jest zapisana binarnie. Użyjemy funkcji: bin(numer_bitu, liczba_int); Liczymy długość pętli: N = ceil(log2(b)); res = 1; mul = a; for( i = 0; i < N; i++ ){ res *= bit(i, b) ? mul : 1; mul *= mul; } To cały algorytm - jedna pętla. Nie jest to co prawda rekursja, ale jak wiadomo rekursję można zrealizować iteracyjnie i vice versa. Tak przy okazji to dokładnie w ten sam sposób działa algorytm szybkiego mnożenia, tylko że tam zamiast *=, będzie +=, oraz niezmiennik mnożenia (1), będzie zastąpiony niezmiennikiem dodawania (0). Ten post edytował flashdev 18.08.2010, 10:25:11 -------------------- |
|
|
![]()
Post
#9
|
|
![]() Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Swój algorytm oparłem o logiczne przemyślenie kroków, bez optymalizacji w stylu "przechodzimy na binarkę", czyli cały czas trzymając się systemu dziesiętnego
![]() Ogólnie jednak rzecz ujmując na pomysł z ifem na bitowej reprezentacji potęgi nie wpadłem, a faktycznie przyspiesza całość bo rozwiązuje problem "potem sprawdzając czy mnożenie potęgi aktualnej * 2 jest większe od wymaganej" w sposób nie wymagający dużej ilości sprawdzeń. Raptem jedno by sprawdzić czy binarna wersja ma ustawione 1 dla tejże pozycji ![]() -------------------- Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
|
|
|
![]()
Post
#10
|
|
![]() Grupa: Zarejestrowani Postów: 812 Pomógł: 117 Dołączył: 2.12.2008 Ostrzeżenie: (10%) ![]() ![]() |
No skoro ta różnica będzie niezauważalna, albo nawet bardzo mała, to po co komplikować sobie życie i wprowadzać jakieś if`y?
![]() A co do tego algorytmu, to gwarantuję Ci, że gdziekolwiek nie spojrzysz na jakieś sprzętowe implementacje potęgowania, lub gotowe wbudowane funkcje w języki programowania, to właśnie będzie to tak zrobione. A i należy jeszcze pamiętać, że tutaj wspomniany przez Ciebie koprocesor będzie miał wątpliwe zastosowanie, bo już przy skromnym wykładniku potęgi > 32 i postawie potęgi równej 2 wychodzimy poza zakres int, więc jest konieczne użycie własnego typu danych. -------------------- |
|
|
![]()
Post
#11
|
|
![]() Grupa: Zarejestrowani Postów: 380 Pomógł: 59 Dołączył: 24.04.2010 Skąd: London Ostrzeżenie: (0%) ![]() ![]() |
Dziękuję bardzo za wyczerpujące odpowiedzi ale czy może ktoś powiedzieć w którym Dokłanie miejscu bufor powinien zbierać informacje a w którym sprawdzać czy dany wynik już wystąpił?
-------------------- |
|
|
![]()
Post
#12
|
|
![]() Grupa: Zarejestrowani Postów: 812 Pomógł: 117 Dołączył: 2.12.2008 Ostrzeżenie: (10%) ![]() ![]() |
Ponieważ nie wytłumaczyłem (uznałem to za oczywiste) co robi moja funkcja bin, a autor tematu dopytuje się o nią na PW zamieszczam poniżej co miałem na myśli.
-------------------- |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 16.05.2025 - 11:10 |