Документация по Python

Возведение в степень

Возведение в степень
В: Документация по Python

Квадратный корень: math.sqrt () и cmath.sqrt

math модуль содержит math.sqrt() -функции , который может вычислить квадратный корень из любого числа (которые могут быть преобразованы в float ) , и результат всегда будет float :

import math

math.sqrt(9)                # 3.0
math.sqrt(11.11)            # 3.3331666624997918
math.sqrt(Decimal('6.25'))  # 2.5

 

math.sqrt() функция вызывает ValueError , если результат будет complex :

math.sqrt(-10)              
 

ValueError: ошибка математического домена

math.sqrt(x) быстрее , чем math.pow(x, 0.5) или x ** 0.5 , но точность результатов является то же самое. cmath модуль очень похож на math модуля, за исключением того , что можно вычислить комплексные числа , и все его результаты в виде + би исключением. Он может также использовать .sqrt() :

import cmath

cmath.sqrt(4)  # 2+0j
cmath.sqrt(-4) # 2j

 

Что с j ? j является эквивалентом квадратного корня из -1. Все числа можно записать в виде a + bi или в этом случае a + bj. реальная часть числа , как 2 в 2+0j . Так как она не имеет мнимую часть, b равно 0. b представляет собой часть мнимой части числа , как 2 - в 2j . Поскольку нет никакой реальной части в этом, 2j также можно записать в виде 0 + 2j .

Экспонирование с использованием встроенных функций: ** и pow ()

Возведение может быть использован с помощью встроенного pow -функции или ** оператора:

2 ** 3    # 8
pow(2, 3) # 8

Для большинства (все в Python 2.x) арифметических операций тип результата будет типом более широкого операнда. Это не верно для ** ; следующие случаи являются исключениями из этого правила:

Основание: int , показатель: int < 0 :

2 ** -3
# Out: 0.125 (result is a float) 

Это также верно для Python 3.x.

Перед Python 2.2.0, это поднял ValueError .

Основание: int < 0 или float < 0 , показатель: float != int

(-2) ** (0.5)  # also (-2.) ** (0.5)# Out: 0.125 (result is a float) 
Out: (8.659560562354934e-17+1.4142135623730951j) (result is complex)


operator модуль содержит две функции, которые эквивалентны ** -оператора:

import operator
operator.pow(4, 2)      # 16
operator.__pow__(4, 3)  # 64

 

или можно напрямую вызвать __pow__ метод:

val1, val2 = 4, 2
val1.__pow__(val2)      # 16
val2.__rpow__(val1)     # 16
# in-place power operation isn't supported by immutable classes like int, float, complex:
# val1.__ipow__(val2)    

Экспонирование с использованием математического модуля: math.pow()

math модуль содержит другой math.pow() функцию. Разница в встроено pow() -функции или ** оператора является то , что результат всегда float :

import math
math.pow(2, 2)    # 4.0
math.pow(-2., 2)  # 4.0

 

Что исключает вычисления со сложными входами:

math.pow(2, 2+0j) 
 

Ошибка типа: невозможно преобразовать сложное в плавающее

и вычисления, которые привели бы к сложным результатам:

math.pow(-2, 0.5)
 

ValueError: ошибка математического домена

Экспоненциальная функция: math.exp () и cmath.exp ()

Как math и cmath модуль содержит число Эйлера: е и использовать его с встроено pow() -функции или ** -оператором работает в основном как math.exp() :

import math

math.e ** 2  # 7.3890560989306495
math.exp(2)  # 7.38905609893065

import cmath
cmath.e ** 2 # 7.3890560989306495
cmath.exp(2) # (7.38905609893065+0j)

Однако результат отличается и использованием экспоненциальной функция непосредственно является более надежной , чем с встроенным базовым возведением в степень math.e :

print(math.e ** 10)       # 22026.465794806703
print(math.exp(10))       # 22026.465794806718
print(cmath.exp(10).real) # 22026.465794806718
#     разница начиется в 11 знаке ----------^ 

Экспоненциальная функция минус 1: math.expm1()

math модуль содержит expm1() -функции , который может вычислить выражение math.e ** x - 1 при очень малых x с более высокой точностью , чем math.exp(x) или cmath.exp(x) позволит:

import math

print(math.e ** 1e-3 - 1)  # 0.0010005001667083846
print(math.exp(1e-3) - 1)  # 0.0010005001667083846
print(math.expm1(1e-3))    # 0.0010005001667083417
#                            ------------------^

 

Для очень маленьких х разница становится больше:

print(math.e ** 1e-15 - 1) # 1.1102230246251565e-15
print(math.exp(1e-15) - 1) # 1.1102230246251565e-15
print(math.expm1(1e-15))   # 1.0000000000000007e-15
#                              ^-------------------

 

Улучшение является значительным в научных вычислениях. Например, закон Планка содержит экспоненциальную функцию минус 1:

def planks_law(lambda_, T):
    from scipy.constants import h, k, c  # Если scipy не установлен, задайте их вручную!
    return 2 * h * c ** 2 / (lambda_ ** 5 * math.expm1(h * c / (lambda_ * k * T)))

def planks_law_naive(lambda_, T):
    from scipy.constants import h, k, c  # If no scipy installed hardcode these!
    return 2 * h * c ** 2 / (lambda_ ** 5 * (math.e ** (h * c / (lambda_ * k * T)) - 1))

planks_law(100, 5000)        # 4.139080074896474e-19
planks_law_naive(100, 5000)  # 4.139080073488451e-19
#                                        ^---------- 

planks_law(1000, 5000)       # 4.139080128493406e-23
planks_law_naive(1000, 5000) # 4.139080233183142e-23
#                                      ^------------ 

Магические методы и возведение в степень: построение, математика и математика

Предположим, у вас есть класс, который хранит чисто целочисленные значения:

class Integer(object):
    def __init__(self, value):
        self.value = int(value) # Cast to an integer

    def __repr__(self):
        return '{cls}({val})'.format(cls=self.__class__.__name__,
                                     val=self.value)

    def __pow__(self, other, modulo=None):
        if modulo is None:
            print('Using __pow__')
            return self.__class__(self.value ** other)
        else:
            print('Using __pow__ with modulo')
            return self.__class__(pow(self.value, other, modulo))

    def __float__(self):
        print('Using __float__')
        return float(self.value)

    def __complex__(self):
        print('Using __complex__')
        return complex(self.value, 0)

 

Использование встроенной pow функции или ** оператор всегда вызывает __pow__ :

Integer(2) ** 2                 # Integer(4)
# Prints: Using __pow__
Integer(2) ** 2.5               # Integer(5)
# Prints: Using __pow__
pow(Integer(2), 0.5)            # Integer(1)
# Prints: Using __pow__  
operator.pow(Integer(2), 3)     # Integer(8)
# Prints: Using __pow__
operator.__pow__(Integer(3), 3) # Integer(27)
# Prints: Using __pow__

 

Второй аргумент __pow__() метод может подаваться только с помощью builtin- pow() или путем непосредственного вызова метода:

pow(Integer(2), 3, 4)           # Integer(0)
# Prints: Using __pow__ with modulo
Integer(2).__pow__(3, 4)        # Integer(0) 
# Prints: Using __pow__ with modulo  

 

В то время как math -функции всегда преобразовать его в float и использовать флоат-вычисления:

import math

math.pow(Integer(2), 0.5) # 1.4142135623730951
# Prints: Using __float__

 

cmath -функции попытаться преобразовать его в complex , но может также Откат к float , если нет явного преобразования в complex :

import cmath

cmath.exp(Integer(2))     # (7.38905609893065+0j)
# Prints: Using __complex__

del Integer.__complex__   # Deleting __complex__ method - instances cannot be cast to complex

cmath.exp(Integer(2))     # (7.38905609893065+0j)
# Prints: Using __float__ 

Ни math , ни cmath будет работать , если также __float__() -метод отсутствует:

del Integer.__float__  # Deleting __complex__ method

math.sqrt(Integer(2))  # also cmath.exp(Integer(2))
 

Ошибка типа: требуется плавающее число

Модульное возведение в степень: pow() с 3 аргументами

Обеспечение pow() с аргументами 3 pow(a, b, c) оценивает модульного возведения в степень а б мод C:

pow(3, 4, 17)   # 13

# equivalent unoptimized expression:
3 ** 4 % 17     # 13

# steps:
3 ** 4          # 81
81 % 17         # 13

 

Для встроенных типов использование модульного возведения в степень возможно только в том случае, если:

  • Первый аргумент является int
  • Второй аргумент является int >= 0
  • Третий аргумент является int != 0

Эти ограничения также присутствуют в Python 3.x

Например, можно использовать 3-аргумент форму pow определить модульную обратную функцию:

def modular_inverse(x, p):
    """Find a such as  a·x ≡ 1 (mod p), assuming p is prime."""
    return pow(x, p-2, p)

[modular_inverse(x, 13) for x in range(1,13)]
# Out: [1, 7, 9, 10, 8, 11, 2, 5, 3, 4, 6, 12]

 

Корни: n-корень с дробными показателями

В то время как math.sqrt функция предусмотрена для конкретного случая квадратных корней, это часто бывает удобно использовать оператор возведения в степень ( ** ) с дробными показателями для выполнения п-корневые операции, как кубические корни.

Обратное возведение в степень является возведением в степень по взаимности экспоненты. Таким образом, если вы можете кубизировать число, указав его в показателе степени 3, вы можете найти корень куба в числе, указав его в показателе 1/3.

>>> x = 3
>>> y = x ** 3
>>> y
27
>>> z = y ** (1.0 / 3)
>>> z
3.0
>>> z == x
True 

Вычисление больших целочисленных корней

Несмотря на то, что Python изначально поддерживает большие целые числа, получение n-го корня очень больших чисел может привести к сбою в Python.

 x = 2 ** 100
cube = x ** 3
root = cube ** (1.0 / 3)

 

OverflowError: long int слишком велико для преобразования в float

При работе с такими большими целыми числами вам нужно будет использовать пользовательскую функцию для вычисления n-го корня числа.

def nth_root(x, n):
    # Start with some reasonable bounds around the nth root.
    upper_bound = 1
    while upper_bound ** n <= x:
        upper_bound *= 2
    lower_bound = upper_bound // 2
    # Keep searching for a better result as long as the bounds make sense.
    while lower_bound < upper_bound:
        mid = (lower_bound + upper_bound) // 2
        mid_nth = mid ** n
        if lower_bound < mid and mid_nth < x:
            lower_bound = mid
        elif upper_bound > mid and mid_nth > x:
            upper_bound = mid
        else:
            # Found perfect nth root.
            return mid
    return mid + 1

x = 2 ** 100
cube = x ** 3
root = nth_root(cube, 3)
x == root
# True
Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.