Экспоненциальность в Python - должен ли я использовать оператор ** вместо math.pow и math.sqrt?
В моей области очень распространено квадратное число чисел, управлять ими вместе и принимать квадратный корень из результата. Это делается в теореме пифагора и, например, вычислении RMS.
В numpy я сделал следующее:
result = numpy.sqrt(numpy.sum(numpy.pow(some_vector, 2)))
И в чистом питоне ожидалось что-то вроде этого:
result = math.sqrt(math.pow(A, 2) + math.pow(B,2)) # example with two dimensions.
Однако я использовал эту чистую форму python, так как я нахожу ее более компактной, независимой от импорта и, по-видимому, эквивалентной:
result = (A**2 + B**2)**0.5 # two dimensions
result = (A**2 + B**2 + C**2 + D**2)**0.5
Я слышал, что некоторые люди утверждают, что оператор **
является своего рода хаком, и возведение в квадрат числа путем экспонирования его на 0.5
не так читаемо. Но я хотел бы спросить, если:
"Существует ли какая-либо КОМПЬЮТЕРНАЯ причина предпочесть предыдущие две альтернативы по сравнению с третьим (ыми)?"
Спасибо за чтение!
Ответы
Ответ 1
math.sqrt
является реализацией C с квадратным корнем и поэтому отличается от использования оператором **
, который реализует встроенную функцию pow
Python. Таким образом, использование math.sqrt
фактически дает другой ответ, чем использование оператора **
, и действительно есть вычислительная причина предпочесть реализацию модуля numpy
или math
над встроенным. В частности, функции sqrt, вероятно, реализованы наиболее эффективным способом, тогда как **
работает с большим количеством баз и экспонентов и, вероятно, не оптимизирован для конкретного случая квадратного корня. С другой стороны, встроенная функция pow
обрабатывает несколько дополнительных случаев, таких как "комплексные числа, неограниченные целые степени и модульное возведение в степень".
См. этот вопрос о переполнении стека для получения дополнительной информации о разнице между **
и math.sqrt
.
В терминах, которые больше "Pythonic" , я думаю, нам нужно обсудить само определение этого слова. Из официального глоссария Python, в нем говорится, что фрагмент кода или идея Pythonic, если он "следует за наиболее распространенными идиомами языка Python, а не внедрять код, используя общие для других языков понятия" . На каждом другом языке, о котором я могу думать, есть математический модуль с основными функциями квадратного корня. Однако существуют языки, в которых отсутствует оператор мощности, например **
, например. С++. Таким образом, **
, вероятно, больше Pythonic, но независимо от того, объективно ли это зависит от использования.
Ответ 2
Даже в базовом Python вы можете выполнить вычисление в общей форме
result = sum(x**2 for x in some_vector) ** 0.5
x ** 2
, конечно же, не является взломом, и вычисление выполняется одинаково (я проверил с исходным кодом cpython). Я на самом деле считаю его более читаемым (и читаемость).
Используя вместо этого x ** 0.5
, чтобы взять квадратный корень, не выполняет то же самое вычисление, что и math.sqrt
, поскольку первое (возможно) вычисляется с использованием логарифмов, а второе (возможно) с использованием конкретной числовой инструкции математического процессора.
Я часто использую x ** 0.5
просто потому, что я не хочу добавлять math
только для этого. Я бы ожидал, однако, что конкретная инструкция для квадратного корня работать лучше (точнее), чем многоступенчатая операция с логарифмами.