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

Другие вопросы по тегам