Подтвердить что ты не робот

Экспоненциальность в 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 не так читаемо. Но я хотел бы спросить, если:

"Существует ли какая-либо КОМПЬЮТЕРНАЯ причина предпочесть предыдущие две альтернативы по сравнению с третьим (ыми)?"

Спасибо за чтение!

4b9b3361

Ответ 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 только для этого. Я бы ожидал, однако, что конкретная инструкция для квадратного корня работать лучше (точнее), чем многоступенчатая операция с логарифмами.