Квадратный корень: 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