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

Введение

Примеры

  • Квадратный корень: 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: (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
    #     difference starts here ---------------^ 
  • Экспоненциальная функция минус 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  # If no scipy installed hardcode these!
        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

Синтаксис

Параметры

Примечания