2013-09-23 10 views
48

Na moim polu bardzo często należy wyrównywać liczby, operować nimi razem i pobierać pierwiastek kwadratowy z wyniku. Odbywa się to na podstawie twierdzenia Pitagorasa, a na przykład obliczenia RMS.Potęgowanie w Pythonie - czy powinienem preferować operatora ** zamiast math.pow i math.sqrt?

W numpy, mam zrobić, co następuje:

result = numpy.sqrt(numpy.sum(numpy.pow(some_vector, 2))) 

A w czystej Pythona coś takiego należy się spodziewać, że:

result = math.sqrt(math.pow(A, 2) + math.pow(B,2)) # example with two dimensions. 

Jednak, byłem przy użyciu tej czystej postaci Pythona, ponieważ Uważam, że to znacznie bardziej zwarty, import-niezależne, a pozornie równoważne:

result = (A**2 + B**2)**0.5 # two dimensions 
result = (A**2 + B**2 + C**2 + D**2)**0.5 

słyszałem niektórzy twierdzą, że operator ** jest w pewnym sensie hackerem, a wyrównywanie liczby przez potęgowanie go przez 0.5 nie jest tak czytelne. Ale chciałbym zapytać, czy:

"Czy istnieje jakikolwiek KOMPUTACYJNY powód, aby preferować poprzednie dwie alternatywy w stosunku do trzeciej (tych)?"

Dzięki za przeczytanie!

+1

Może to być odpowiedni temat - http://stackoverflow.com/questions/327002/which-is-faster-in-python-x-5-or-math-sqrtx –

+1

Mam tendencję myśleć, że math.sqrt() jest bardziej czytelny niż() ** 0.5. –

+1

@Maxime, chciałbym pójść jeszcze dalej i po prostu użyć 'sqrt' z' od matematyki import sqrt'. –

Odpowiedz

43

math.sqrt to implementacja C pierwiastka kwadratowego, dlatego różni się od użycia operatora **, który implementuje wbudowaną funkcję Pythona pow. Tak więc, używanie math.sqrt faktycznie daje inną odpowiedź niż użycie operatora ** i rzeczywiście istnieje powód, aby preferować implementację modułu numpy lub math przez wbudowane. W szczególności funkcje sqrt są prawdopodobnie implementowane w najbardziej wydajny sposób, podczas gdy ** działa na dużej liczbie baz i wykładników i prawdopodobnie nie jest optymalizowane dla konkretnego przypadku pierwiastka kwadratowego. Z drugiej strony wbudowana funkcja pow obsługuje kilka dodatkowych przypadków, takich jak "liczby zespolone, nieograniczone moce całkowite i modułowe potęgowanie".

See this Stack Overflow question for more information on the difference between ** and math.sqrt.

Pod względem która jest bardziej „pythonowy”, myślę, że musimy omówić samą definicję tego słowa. Z wersji the official Python glossary wynika, że ​​fragment kodu lub idei jest Pythonic, jeśli "ściśle podąża za najczęstszymi idiomami języka Python, a nie zaimplementowaniem kodu przy użyciu pojęć wspólnych dla innych języków."W każdym innym języku, jaki mogę sobie wyobrazić, jest jakiś moduł matematyczny z podstawowymi funkcjami pierwiastków kwadratowych, ale są języki, które nie mają operatora mocy takiego jak ** np. C++. Tak więc ** jest prawdopodobnie bardziej Pythoniczny, ale czy jest obiektywnie lepszy zależy od przypadku użycia:

+0

Skąd 'operator.pow' wchodzi w miks? –

+0

Doskonała odpowiedź, w szczególności za wzięcie czegoś, co mogło być bardzo "upartym" tematem i skupienie się na OP, a także na istotnych najemcach Pythona. Sława. – GrayedFox

+0

Jednak jeśli wejściami są liczby całkowite, ** lub wbudowana funkcja pow może być preferowana obliczeniowo: "W odróżnieniu od wbudowanego operatora **, math.pow() konwertuje oba swoje argumenty na typ float. wbudowana funkcja pow() do obliczania dokładnych mocy całkowitych. " - Python docs: biblioteka matematyczna https://docs.python.org/2/library/math.html#power-and-logarithmic-functions – hyperGeoMetric

12

Nawet w podstawowej Pythonie można wykonać obliczenia w postaci generycznej

result = sum(x**2 for x in some_vector) ** 0.5 

x ** 2 nie jest z pewnością siekać i obliczenia wykonywane jest taka sama (sprawdziłem z kodem źródłowym CPython). W rzeczywistości uważam, że jest bardziej czytelny (i liczy się czytelność).

Użycie zamiast niego x ** 0.5 do wykonania pierwiastka kwadratowego nie wykonuje dokładnie tych samych obliczeń, co math.sqrt, ponieważ pierwsze (prawdopodobnie) jest obliczane przy użyciu logarytmów, a drugie (prawdopodobnie) przy użyciu określonej instrukcji numerycznej procesora matematycznego.

Często używam x ** 0.5 po prostu dlatego, że nie chcę dodawać po prostu math. Spodziewam się jednak, że specjalna instrukcja dla pierwiastka kwadratowego będzie działała lepiej (dokładniej) niż operacja wieloetapowa z logarytmami.

+2

Podobno [nie jest dokładniejsze] (http://stackoverflow.com/a/842358/199360) - ale [sqrt jest szybszy] (http://stackoverflow.com/a/327011/199360). – adib

+0

Dlaczego interpreter języka Python nie rozpoznaje x ** 0,5 jako wyjątku? Po wszystkim 0,5 jest stałą. – user3150208

Powiązane problemy