Экспонирование в 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
не так читабельно. Но я хотел бы спросить, если:
"Есть ли какая-либо ВЫЧИСЛИТЕЛЬНАЯ причина, чтобы предпочесть первые две альтернативы третьей (ым)?"
Спасибо за прочтение!
2 ответа
math.sqrt
это реализация C квадратного корня и, следовательно, отличается от использования **
оператор, который реализует встроенный в Python pow
функция. Таким образом, используя math.sqrt
на самом деле дает другой ответ, чем с помощью **
оператор и действительно есть вычислительная причина, чтобы предпочесть numpy
или же math
Реализация модуля поверх встроенного. В частности, функции sqrt, вероятно, реализованы наиболее эффективным способом, в то время как **
работает на большом количестве оснований и показателей и, вероятно, неоптимизирован для конкретного случая квадратного корня. С другой стороны, встроенный pow
Функция обрабатывает несколько дополнительных случаев, таких как "комплексные числа, неограниченные целочисленные степени и возведение в модуляр".
См. Этот вопрос переполнения стека для получения дополнительной информации о разнице между **
а также math.sqrt
,
Что касается более "Pythonic", я думаю, что мы должны обсудить само определение этого слова. В официальном глоссарии Python говорится, что часть кода или идеи является Pythonic, если она "близко следует наиболее распространенным идиомам языка Python, а не реализует код с использованием концепций, общих для других языков". В любом другом языке, о котором я могу думать, есть некоторый математический модуль с основными функциями квадратного корня. Однако есть языки, в которых отсутствует мощный оператор, такой как **
например, C++. Так **
вероятно, более Pythonic, но объективно лучше или нет, зависит от варианта использования.
Даже в базовом Python вы можете сделать вычисления в общей форме
result = sum(x**2 for x in some_vector) ** 0.5
x ** 2
это, конечно, не хак, и выполняемые вычисления одинаковы (я проверял исходный код cpython). Я на самом деле считаю его более читабельным (и читаемость считается).
Использование вместо x ** 0.5
взять квадратный корень не делает точно такие же вычисления, как math.sqrt
поскольку первое (вероятно) вычисляется с использованием логарифмов, а второе (вероятно) с использованием конкретной числовой инструкции математического процессора.
Я часто использую x ** 0.5
просто потому что я не хочу добавлять math
только для этого. Однако я ожидаю, что конкретная инструкция для квадратного корня будет работать лучше (точнее), чем многошаговая операция с логарифмами.