Числа произвольной точности в Python: int, Decimal и Fraction
Работа с большими числами в Python
Python предоставляет встроенный тип int, который поддерживает целые числа произвольной точности. Это означает, что размер числа ограничен только доступной памятью. Для базовых арифметических операций (сложение, вычитание, умножение, возведение в степень) не происходит переполнения, как в языках с фиксированной разрядностью. Пример:
>>> a = 10**1000
>>> a
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
вывести дзен python командой import this (вывод дзен python командой import this)
Операции с такими числами выполняются напрямую:
>>> b = 2**100000
>>> len(str(b))
30103
большие числа python (большие числа в python)
Как выполнять вычисления с десятичными дробями высокой точности?
Тип float имеет ограниченную точность (около 15 знаков) и может представлять только приближённые значения для больших чисел. Для точных десятичных вычислений применяется модуль decimal. Он позволяет задавать произвольную точность.
from decimal import Decimal, getcontext
getcontext().prec = 50
d1 = Decimal('1') / Decimal('3')
print(d1) # 0.33333333333333333333333333333333333333333333333333
Такой подход применяется в финансовых расчётах, где недопустимы ошибки округления.
Как избежать потери точности при делении больших целых чисел?
При делении целых чисел оператор / возвращает float, что может привести к потере точности для очень больших чисел. Рекомендуется применять целочисленное деление // или модуль decimal.
>>> huge = 10**50
>>> huge / 3 # float, точность потеряна
3.3333333333333335e+49
>>> huge // 3 # целое
33333333333333333333333333333333333333333333333333
Как работать с рациональными числами?
Модуль fractions позволяет точно представлять дроби, избегая ошибок округления. Это полезно при математических вычислениях, где важна точность.
from fractions import Fraction
frac = Fraction(1, 3)
print(frac) # 1/3
print(frac * 3) # 1
Как ускорить операции с очень большими числами?
Стандартный int в Python уже использует алгоритмы быстрого умножения (Карацуба, Toom-Cook, FFT) для больших чисел. Однако для сверхбольших чисел (сотни тысяч бит) можно воспользоваться библиотекой gmpy2, которая реализует высокопроизводительные операции на C.
import gmpy2
a = gmpy2.mpz(10**10000)
b = gmpy2.mpz(10**10000)
c = a * b # очень быстро
Важно: gmpy2 является сторонней библиотекой, её нужно устанавливать отдельно.
Как обрабатывать числа, не помещающиеся в оперативную память?
Если число настолько велико, что его нельзя сохранить в памяти целиком (например, при работе с последовательностями цифр), можно использовать итеративный подход или запись на диск. Python не предоставляет прямой поддержки таких чисел, но можно использовать массивы модуля array или numpy с типом object для работы с большими числами по частям.
# Пример: генерация гигантского числа по частям
def large_number_by_parts():
parts = []
for _ in range(1000):
parts.append('9' * 1000)
return int(''.join(parts))
Типичные ошибки и проблемы
- Переполнение float: при попытке сохранить число > 1.8e308 в float возникает ошибка OverflowError. В таких ситуациях лучше использовать decimal или int.
- MemoryError: при создании int с миллиардами цифр может не хватить памяти. Стоит разбивать вычисления на части.
- Медленные операции: возведение в степень или умножение для чисел из сотен тысяч бит может занимать секунды. Для ускорения можно оптимизировать алгоритмы или применить gmpy2.
- Потеря точности при преобразовании: преобразование очень большого int в float приводит к потере точности. Такого преобразования следует избегать.
- Неправильное округление: при использовании decimal важно установить точность через getcontext().prec.
Расширенные примеры работы с большими числами
# Вычисление факториала 1000 с помощью int
import math
fact = math.factorial(1000)
print(f"Факториал 1000 содержит {len(str(fact))} цифр")
Факториал 1000 содержит 2568 цифр
# Сравнение точности float и decimal при сложении больших чисел
from decimal import Decimal, getcontext
getcontext().prec = 30
float_sum = 1e30 + 1 - 1e30
decimal_sum = Decimal('1e30') + Decimal('1') - Decimal('1e30')
print(f"float: {float_sum}") # 0.0 из-за потери точности
print(f"decimal: {decimal_sum}") # 1
float: 0.0 decimal: 1
# Использование fractions для точного представления периодических дробей
from fractions import Fraction
f = Fraction(1, 7)
print(f) # 1/7
# Возведение в степень
print(f ** 10)
1/7 1/282475249
# Вычисление числа Пи через decimal с высокой точностью (ряд Лейбница)
from decimal import Decimal, getcontext
getcontext().prec = 100
pi = Decimal(0)
for i in range(1000):
sign = 1 if i % 2 == 0 else -1
pi += Decimal(sign) / Decimal(2*i + 1)
pi *= 4
print(pi)
3.1405926538397929259552365024037352294921875... (точность ~3.14)
# Демонстрация работы целых чисел произвольной точности: число 2**100000 имеет 30103 цифры
a = 2**100000
print(len(str(a)))
30103
# Умножение двух больших чисел: 10**10000 * 10**10000
a = 10**10000
b = 10**10000
c = a * b
print(f"Количество цифр результата: {len(str(c))}")
Количество цифр результата: 20001
# Пример использования gmpy2 для ускорения (требуется установка pip install gmpy2)
import gmpy2
x = gmpy2.mpz(2) ** 1000000
print(f"gmpy2: число содержит {len(str(x))} цифр")
gmpy2: число содержит 301030 цифр