complexКомплексные числа - это числа вида a+bi, где:
a - действительная частьb - мнимая частьi - мнимая единица, для которой выполняется i^2 = -1Числа a и b являются действительными. Если a = 0, то комплексное число превращается в чисто мнимое, а если b = 0, то в действительное.
Комплексные числа нужны чтобы получить решение уравнений, которые невозможно решить в действительных числах.
В Python комплексные числа являются встроенным типом данных
complex(real=1, imag=2)
# или
complex("1+2j")
complex() создаёт комплексное число со значением real + imag * 1j или преобразует строку в комплексное число, если первым аргументом передана строка.
В Python используется символ j, но в математике обычно i.
Если первый аргумент строка, то он интерпретируется как комплексное число в формате a+bj, a, +bj, -bj. В этом случае второй аргумент передавать не надо - будет ошибка.
При создании из строки формат должен быть строго написан, чтобы Python понял его. Допустимы “a+bj”, “a”, “bj”, “-bj”, “+bj”, но без пробелов около +/- и j. j (или J) - единственно допустимая буква для мнимой единицы. Если cтрока не может быть распознана как комплексное число возникает ValueError.
Если оба аргумента опущены, то возвращается 0j.
# Удобный и рекомендуемый способ
z1 = 1 + 2j # (1+2j)
# Через complex()
z2 = complex(1,2) # (1+2j)
z3 = complex(5) # (5+0j)
z4 = complex() # (0+0j)
z5 = complex("1+2j") # (1+2j)
z6 = complex("-3.5+0j") # (-3.5+0j)
z7 = complex("7j") # 0+7j
Все арифметические операции работают как в математике
a = 3 + 4j
b = 1 - 2j
print(a + b) # (4+2j)
print(a - b) # (2+6j)
print(a * b) # (11+2j)
print(a / b) # (-1+2j)
print(a ** 2) # (-7+24j)
# Сравнение
# Комплексные числа можно сравнивать только на равенство
print(a == complex(3,4)) # True
print(b == 3+4j) # False
# Модуль (абсолютное значение)
print(abs(a)) # 5.0
print(abs(0+1j)) # 1.0
complex()
z = 3 + 4j
print(z.real) # 3.0 - вещественная часть (всегда float)
print(z.imag) # 4.0 - мнимая часть (всегда float)
print(z.conjugate()) # (3-4j) - комплексно-сопряжённое число
print(abs(z)) # 5.0 - модуль числа (|z| = √(a^2 + b^2))
cmathОбычный модуль math не работает с комплексными числами. Поэтому чтобы использовать большинство математических операций (для тригонометрии, логарифмов, экспоненты и тд.) нужно использовать библиотеку cmath:
import cmath
print(cmath.sqrt(-1)) # 1j
print(cmath.sqrt(-9)) # 3j
print(cmath.log(-1)) # 3.141592653589793j
print(cmath.sin(1j)) # 1.1752
print(cmath.cos(1j)) # 1.5431
fractionsМодуль fractions - это стандартная библиотека Python, которая позволяет работать с рациональными числами (обыкновенными дробями) с математической точностью. Библиотека предоставляет класс Fraction для работы с рациональными числами.
В отличие от типа float, который хранит приближённые значения с плавающей точкой и часто даёт ошибки округления(0.1 + 0.2 != 0.3), тип данных Fraction представляет число в виде несократимой дроби вида p/q, где p и q - целые числа, а q != 0.
Fraction является неизменяемым типом данных (immutable), как int, float, str, tuple. Это означает, что после создания объекта Fraction его нельзя изменить - все операции возвращают новый объект.
Преимущества:
Недостатки:
floatFraction
from fractions import Fraction
a = Fraction(3, 4) # 3/4
b = Fraction(8, 12) # 2/3 - сразу сокращается
с = Fraction(5) # 5/1 - если указан только числитель
d = Fraction() # 0/1 (по умолчанию)
# Из строки
e = Fraction("0.75") # 3/4 - надёжный способ создания из строки
f = Fraction('3/4') # 3/4
g = Fraction('2.5') # 5/2
h = Fraction(' -3/7 ') # -3/7 - пробелы игнорируются
** Важная рекомендация **
Не создавайте Fraction напрямую из float, если точность важна:
# Плохо - потеря точности
print(Fraction(0.1)) # 3602879701896397/36028797018963968
# Правильно - точное значение
print(Fraction("0.1")) # 1/10
** Знаменатель всегда > 0, знак хранится в числителе **
a = Fraction(-3, 4) # -3/4
b = Fraction(3, -4) # -3/4 - знак переносится в числитель
Тип данных Fraction поддерживает все арифметические операции
a = Fraction(1, 3)
b = Fraction(1, 6)
print(a + b) # 1/2
print(a - b) # 1/6
print(a * b) # 1/18
print(a / b) # 2/1
print(a ** 2) # 1/9
print(-a) # -1/3
# С целыми числами
print(Fraction(3, 4) + 1) # 7/4
print(Fraction(3, 4) * 2) # 3/2
# С float - результат становится float
print(Fraction(1, 2) + 0.5) # 1.0
Сравнение работает точно так же, как и любые другие числа
Fraction(1, 2) == Fraction(2, 4) # True
Fraction(1, 3) > Fraction(1, 4) # True
Fraction(3, 4) < 1 # True
Fraction(4, 2) == 2 # True
# Можно сравнивать с float
Fraction(1, 2) == 0.5 # True
Fraction числа можно передавать как аргументы функций, ожидающих float. Тогда они будут преобразованы во float. К примеру, модуль math, может работать и с Fraction числами.
from fractions import Fraction
from math import *
num1 = Fraction('1.44')
num2 = Fraction('0.523')
print(sqrt(num1)) # 1.2
print(sin(num2)) # 0.4994813555186418
print(log(num1 + num2)) # 0.6744739152943241
Для получения отдельно числителя и знаменателя используются свойства numerator и denominator.
from fractions import Fraction
f = Fraction(14, 20)
print(f.numerator) # 14
print(f.denominator) # 20
limit_denominator(max_denominator=1000) — находит и возвращает ближайшую дробь к self, у которой знаменатель не превышает max_denominator. Очень полезно для приближения float к рациональным числам или восстановления дробей из float.
f = Fraction('3.1415926535897932').limit_denominator(1000)
print(f) # 355/113
as_integer_ratio() - Возвращает кортеж (numerator, denominator) — пару целых чисел, равную данной дроби (в несократимом виде, знаменатель > 0).
f = Fraction(3, 4)
print(f.as_integer_ratio()) # (3, 4)
is_integer() - Возвращает True, если дробь является целым числом (знаменатель = 1).
Fraction(5, 1).is_integer() # True
Fraction(5, 2).is_integer() # False
Модуль decimal - это стандартная библиотека Python, предназначенная для точных десятичных вычислений с фиксированной точностью. Библиотека предоставляет класс Decimal для работы с десятичными числами, что особенно важно для финансовых расчетов, бухгалтерии и любых задач, где критически важна точность.
В отличие от типа float, который использует двоичное представление что может приводить к ошибкам округления (0.1 + 0.2 != 0.3), тип Decimal хранит числа в десятичной системе и обеспечивает точность, заданную пользователем.
Decimal является неизменяемым типом данных (immutable), как int, float, str, tuple. Это означает, что после создания объекта Decimal его нельзя изменить - все операции возвращают новый объект.
Преимущества:
Infinity, -Infinity, NaN)Недостатки:
floatDecimal
from decimal import Decimal
# Из целого числа
a = Decimal(10) # 10
b = Decimal(-5) # -5
# Из строки (РЕКОМЕНДУЕМЫЙ способ для десятичных дробей)
c = Decimal("10.75") # 10.75
d = Decimal("-3.14159") # -3.14159
e = Decimal("0.1") # 0.1
# Специальные значения
f = Decimal("Infinity") # Infinity
g = Decimal("-Infinity") # -Infinity
h = Decimal("NaN") # NaN (Not a Number)
** Важная рекомендация **
Не создавайте Decimal напрямую из float, если точность важна:
# Плохо - потеря точности
print(Decimal(0.1)) # 0.1000000000000000055511151231257827021181583404541015625
# Правильно - точное значение
print(Decimal("0.1")) # 0.1
Точность и правила округления можно задать через контекст
from decimal import Decimal, getcontext
# Установка точности (количество значащих цифр по умолчанию 28 цифр)
getcontext().prec = 6 # точность — 6 значащих цифр
print(Decimal(1) / Decimal(3)) # 0.333333
# Смена режима округления
from decimal import ROUND_HALF_UP, ROUND_HALF_EVEN
price = Decimal('19.995')
getcontext().rounding = ROUND_HALF_UP
print(price.quantize(Decimal('0.01'))) # 20.00
getcontext().rounding = ROUND_HALF_EVEN # банковское округление
print(Decimal('2.5').quantize(Decimal('1'))) # 2
print(Decimal('3.5').quantize(Decimal('1'))) # 4
Ещё отдельные режимы округления:
ROUND_CEILING - округление вверх. Всегда округляет в большую сторону
Пример: 2.1 = 3, -2.1 = -2
ROUND_FLOOR - округление вниз. Всегда округляет в меньшую сторону
Пример: 2.9 = 2, -2.9 = -3
ROUND_UP - округление от нуля (для положительных — вверх, для отрицательных — вниз)
Пример: 2.1 = 3, -2.1 = -3
ROUND_DOWN - округление к нулю (усечение)
Пример: 2.9 = 2, -2.9 = -2
ROUND_HALF_UP - школьное округление (0-4 вниз, 5-9 вверх)
Пример: 2.5 = 3, 2.4 = 2
ROUND_HALF_DOWN - округление 5 вниз. 0-4 вниз, 6-9 вверх, 5 тоже вниз
Пример: 2.5 = 2, 2.6 = 3
ROUND_HALF_EVEN - банковское округление 5 округляет к ближайшему четному числу
Пример: 2.5 = 2, 3.5 = 4
Уменьшает статистическую погрешность при сериях операций
1.04 → 1.0, 1.05 → 1.1 (при точности до 0.1)По умолчанию настройки контекста (точность, округление и флаги ошибок),
заданные через getcontext(), являются глобальными и действуют на весь код.
Для временного изменения настроек вычислений используется localcontext().
Он позволяет задать отдельный контекст для ограниченного блока кода,
не влияя на остальную программу.
После выхода из блока with все настройки автоматически возвращаются
к предыдущему состоянию.
from decimal import Decimal, localcontext, getcontext
# Глобальный контекст
getcontext().prec = 28
print(Decimal(1) / Decimal(3)) # 0.3333333333333333333333333333
# Локальный контекст
with localcontext() as ctx:
ctx.prec = 6
print(Decimal(1) / Decimal(3)) # 0.333333
# Глобальный контекст не изменился
print(Decimal(1) / Decimal(3)) # 0.3333333333333333333333333333
Тип Decimal поддерживает все арифметические операции с контролем точности:
a = Decimal("10.5")
b = Decimal("3.2")
print(a + b) # 13.7
print(a - b) # 7.3
print(a * b) # 33.6
print(a / b) # 3.28125
print(a % b) # 0.9
print(a ** 2) # 110.25
print(-a) # -10.5
# Деление с округлением
print(a / b) # 3.28125
print((a / b).quantize(Decimal("0.01"))) # 3.28
# Целочисленное деление
print(a // b) # 3
Сравнение работает точно так же, как и любые другие числа
Decimal("0.1") + Decimal("0.2") == Decimal("0.3") # True
Decimal("1.5") > Decimal("1.0") # True
Decimal("1.5") <= Decimal("1.5") # True
Decimal("1.5") != Decimal("1.0") # True
# Сравнение со специальными значениями
Decimal("Infinity") > Decimal("1000") # True
Decimal("NaN") == Decimal("NaN") # False (NaN != NaN)
Decimal предоставляет собственные математические методы (sqrt, exp, ln, log10), аналогичные функциям math. Возвращает тип Decimal. Обычные math-функции требуют преобразования в float.
from decimal import Decimal, getcontext
import math
d = Decimal("2.25")
print(d.sqrt()) # 1.5 (квадратный корень)
print(d.exp()) # e^2.25
print(d.ln()) # Натуральный логарифм
print(d.log10()) # Десятичный логарифм
# Тригонометрические функции (нужно установить достаточную точность)
getcontext().prec = 30
angle = Decimal("0.523598775598298873") # π/6 ≈ 30°
print(angle.sin()) # 0.5 (синус)
print(angle.cos()) # 0.866025403784438646 (косинус)
print(math.sqrt(float(d))) # 1.5
Decimal
d = Decimal("10.75")
n = Decimal("NaN")
inf = Decimal("Infinity")
print(d.is_finite()) # True - проверка на конченое число
print(d.is_infinite()) # False - проверка на бесконченое число
print(d.is_nan()) # False - проверка на nan
print(d.is_signed()) # False - проверка на отрицательное число
print(Decimal("-10.75").is_signed()) # True
print(d.is_zero()) # False - проверка на ноль
print(n.is_nan()) # True
print(inf.is_infinite()) # True
Decimalquantize(exp, rounding=None) - округление до заданной экспоненты:
price = Decimal("15.6789")
# Округление до 2 знаков после запятой
print(price.quantize(Decimal("0.01"))) # 15.68
print(price.quantize(Decimal("0.01"), rounding=ROUND_DOWN)) # 15.67
# Округление до целого
print(price.quantize(Decimal("1"))) # 16
print(price.quantize(Decimal("1"), rounding=ROUND_DOWN)) # 15
to_integral_value(rounding=None) - округление до целого:
d = Decimal("15.78")
print(d.to_integral_value()) # 16
print(d.to_integral_value(ROUND_DOWN)) # 15
normalize() - нормализация (убирает лишние нули в конце):
d1 = Decimal("100.00")
d2 = Decimal("1.2E+2")
print(d1.normalize()) # 1E+2 (100 в научной нотации)
print(d2.normalize()) # 1.2E+2
# Для получения привычного вида:
print(d1.normalize().to_eng_string()) # 100
as_tuple() - возвращает внутреннее представление числа:
d = Decimal("123.456")
print(d.as_tuple())
# DecimalTuple(sign=0, digits=(1, 2, 3, 4, 5, 6), exponent=-3)
# Можно восстановить Decimal из кортежа
from decimal import DecimalTuple
t = DecimalTuple(sign=0, digits=(1, 2, 3), exponent=0)
print(Decimal(t)) # 123
to_eng_string() - строковое представление в инженерной нотации:
d = Decimal("123456.789")
print(d.to_eng_string()) # 123456.789
adjusted() — возвращает порядок числа (экспоненту):
print(Decimal("123.456").adjusted()) # 2 (10^2)
print(Decimal("0.00123").adjusted()) # -3 (10^-3)