2016-03-23 13 views
7

Jestem samokształceniem C++ i książką "Programowanie - zasady i praktyki przy użyciu C++" autorstwa Bjarne Stroustrup. Jeden z "Spróbuj tego" pyta:Tworzenie funkcji kwadratowej() bez x * x w C++

Kwadrat narzędzia() bez użycia operatora mnożenia; to znaczy, wykonaj x * x, powtarzając dodawanie (rozpocznij zmienny wynik na 0 i dodaj x do niego x razy). Następnie uruchom pewną wersję "pierwszego programu" za pomocą tego kwadratu().

Zasadniczo potrzebuję funkcji kwadratowej (int x), która zwróci jej kwadrat bez użycia operatora mnożenia. Do tej pory mam to:

int square(int x) 
{ 
    int i = 0; 
    for(int counter = 0; counter < x; ++counter) 
    { 
     i = i + x; 
    } 

return i; 
} 

Ale zastanawiałem się, czy istnieje lepszy sposób, aby to zrobić. Powyższa funkcja działa, ale jestem pewien, że nie jest to najlepsza metoda. Jakaś pomoc?

+1

Można użyć przesunięcia i dbają tylko o bity, które są ustawione w lewej-stronie. Tak działa ogólne mnożenie binarne. –

+0

http://stackoverflow.com/questions/2776211/how-can-i-multiply-and-divide-using-only-bit-shifting-and-adding Możesz również użyć funkcji standardowej biblioteki pow oraz kwadratu x. –

+1

Ta implementacja jest jasna i jest dokładnie tą metodą, o którą prosiłeś, aby to zrobić. "Najlepszy" to termin niejasny. – moreON

Odpowiedz

-1

W kadencji Czas złożoności, implementacja jest jasne i wystarczy po prostu, jego czas pracy jest T (n) = Θ (n) dla wejścia n elements.Of Oczywiście można również skorzystać dziel i -Konkursuje metoda, zakładając podział n elementów na n/2: n/2, a na końcu rekursywnie obliczy ją, następnie podsumuje dwie części, że czas działania będzie taki jak T (n) = 2 T (n/2) + Θ (n) = Θ (nlgn), możemy stwierdzić, że jego złożoność czasu działania staje się gorsza niż implementacja.

+0

Nie, poprawnie wykonano Divide-and-Conquer prowadzi do ** T (n) = T (n/2) + Θ (1) **, znacznie lepiej niż ** Θ (n) **. –

+0

@Yves: Myślę, że się mylisz, zakładając, że podzielisz tablicę na średnią wielkość, możesz uzyskać dwa sub-drzewa, a jego rozmiar powinien wynosić ** n/2 **, a gdy rekursywnie spadniesz do liści, powinieneś Podsumuj każdy poziom drzewa rekurencyjnego, który będzie kosztował ** Θ (n) ** czas działania. Więc masz dwa pod-drzewa i przechodzisz przez każdy poziom drzewa rekurencyjnego, aby je podsumować, więc całkowity czas powinien być ** T (n) = 2 T (n/2) + Θ (n) = Θ (nlgn) **. –

+0

Myślę, że mam rację, ** n/2 = n/2 ** i nie ma potrzeby wykonywania dwóch wywołań rekursywnych i nie ma żadnego ** Θ (n) ** terminu. –

4

Mats Petersson ukradł pomysł z mojej głowy, jeszcze zanim pomyślałem, że to wymyśliłem.

#include <iostream> 

template <typename T> 
T square(T x) { 
    if(x < 0) x = T(0)-x; 
    T sum{0}, s{x}; 
    while(s) { 
     if(s & 1) sum += x; 
     x <<= 1; 
     s >>= 1; 
    } 
    return sum; 
} 

int main() { 
    auto sq = square(80); 
    std::cout << sq << "\n"; 
} 
+2

Prawdopodobnie masz na myśli to, że starożytni Egipcjanie ukradli ten pomysł: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication –

+2

Z jednej strony byli grupą szarpnięć za kradzież mojego pomysłu, z drugiej strony ich zdolności psychiczne były niewyobrażalnie silne , więcej niż Mats. Musisz to uszanować. –

+2

W drugiej chwili, po pełnym przeczytaniu linku do Wikipedii, zdaję sobie sprawę, że Rosyjscy Chłopi rzeczywiście ukradli twój pomysł i sami zainspirowali Egipcjan przed wiekami. –

-1

Możesz dołączyć <math.h> lub <cmath> i używać jej sqrt() Funkcja:

#include <iostream> 
#include <math.h> 
int square(int); 

int main() 
{ 
    int no; 
    std::cin >> no; 

    std::cout << square(no); 
    return 0; 
} 

int square(int no) 
{ 
    return pow(no, 2); 
} 
+0

Kwadrat, a nie pierwiastek kwadratowy. –

+0

Sry użyj funkcji pow() zamiast: – JedaiCoder

+0

Przekonasz się, że jest to niedokładne z powodu błędów zaokrąglania zmiennoprzecinkowych. –

0
int square(int x) 
{ 
    int result = 0; 
    for (int counter = 0; counter < x; ++counter) result += x; 
    return result; 
}