Зачем нужны
float хранит числа в двоичном виде, поэтому не подходит для денег и точных расчётов:
print(0.1 + 0.2)print(sum([0.1] * 10) == 1.0)Модуль decimal реализует десятичную арифметику с заданной точностью, fractions — точные рациональные числа.
Decimal
from decimal import Decimala = Decimal("0.1")b = Decimal("0.2")print(a + b)print(a + b == Decimal("0.3"))print(Decimal("1.10") + Decimal("2.205"))Создавайте Decimal из строк. Создание из float сохраняет неточность двоичного представления:
print(Decimal(0.1))print(Decimal("0.1"))print(Decimal.from_float(0.5))Арифметика
x = Decimal("10")y = Decimal("3")print(x / y)print(x // y)print(x % y)print(x ** 2)print(-x)print(abs(Decimal("-2.5")))print(x + 1)Смешивать Decimal с float нельзя — будет TypeError. С целыми числами смешивать можно.
Методы Decimal
| Метод | Описание |
|---|---|
quantize(exp, rounding=None) | Округление до заданного порядка |
to_integral_value() | Округление до целого |
sqrt(), exp(), ln(), log10() | Математические функции |
normalize() | Убирает хвостовые нули |
as_tuple() | Знак, цифры, показатель степени |
is_nan(), is_infinite(), is_finite(), is_zero(), is_signed() | Проверки |
copy_abs(), copy_negate(), copy_sign(other) | Копирование со знаком |
compare(other) | Сравнение с результатом Decimal |
as_integer_ratio() | Дробь |
adjusted() | Показатель старшей цифры |
fma(a, b) | Умножение и сложение за одну операцию |
max(other), min(other) | Максимум и минимум |
Округление
from decimal import Decimal, ROUND_HALF_UP, ROUND_DOWN, ROUND_HALF_EVENprice = Decimal("2.675")print(price.quantize(Decimal("0.01")))print(price.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))print(price.quantize(Decimal("0.01"), rounding=ROUND_DOWN))print(Decimal("2.5").quantize(Decimal("1"), rounding=ROUND_HALF_EVEN))| Режим | Описание |
|---|---|
ROUND_HALF_EVEN | К ближайшему чётному (по умолчанию) |
ROUND_HALF_UP | Половина от нуля |
ROUND_HALF_DOWN | Половина к нулю |
ROUND_UP | От нуля |
ROUND_DOWN | К нулю |
ROUND_CEILING | К плюс бесконечности |
ROUND_FLOOR | К минус бесконечности |
ROUND_05UP | От нуля, если последняя цифра 0 или 5 |
Контекст
from decimal import Decimal, getcontext, localcontextprint(getcontext().prec)getcontext().prec = 10print(Decimal(1) / Decimal(7))with localcontext() as ctx: ctx.prec = 50 print(Decimal(1) / Decimal(7))print(Decimal(1) / Decimal(7))Контекст хранит точность (prec), режим округления (rounding), границы показателя и управление сигналами (traps). Точность по умолчанию — 28 знаков.
Пример: сумма заказа
from decimal import Decimal, ROUND_HALF_UPitems = [("Книга", Decimal("19.99"), 2), ("Ручка", Decimal("1.50"), 5)]subtotal = sum(price * qty for _, price, qty in items)tax = (subtotal * Decimal("0.20")).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)total = subtotal + taxprint(subtotal, tax, total)Fraction
Fraction хранит числитель и знаменатель в виде целых чисел и всегда приводит дробь к несократимому виду:
from fractions import Fractiona = Fraction(1, 3)b = Fraction(2, 6)c = Fraction("3/4")d = Fraction("0.125")e = Fraction(0.5)print(a == b)print(a + c)print(c * d)print(a / c)print(c ** 2)print(Fraction(3, 1))Атрибуты и методы Fraction
| Элемент | Описание |
|---|---|
numerator, denominator | Числитель и знаменатель |
limit_denominator(max) | Ближайшая дробь с ограниченным знаменателем |
as_integer_ratio() | Пара (числитель, знаменатель) |
from_float(x), from_decimal(d) | Классовые методы |
is_integer() | Равна ли целому (Python 3.12+) |
floor, ceil, round, trunc | Через math и round |
import mathfrom fractions import Fractionf = Fraction(7, 2)print(f.numerator, f.denominator)print(math.floor(f), math.ceil(f), round(f))print(float(f))print(Fraction(0.1).limit_denominator(100))print(Fraction(3.14159).limit_denominator(1000))Fraction совместим с Decimal и int в арифметике (с Decimal — нужно явное преобразование), а при сложении с float результат становится float.
Сравнение числовых типов
| Тип | Точность | Скорость | Применение |
|---|---|---|---|
int | Точный | Высокая | Целые значения |
float | ≈ 15–17 цифр | Очень высокая | Научные расчёты, графика |
Decimal | Заданная десятичная | Низкая | Деньги, бухгалтерия |
Fraction | Точная рациональная | Низкая | Точные дроби, математика |
complex | Как float | Высокая | Сигналы, физика |
Модуль numbers описывает иерархию числовых типов:
import numbersfrom decimal import Decimalfrom fractions import Fractionprint(isinstance(1, numbers.Integral))print(isinstance(Fraction(1, 2), numbers.Rational))print(isinstance(1.5, numbers.Real))print(isinstance(1j, numbers.Complex))print(isinstance(Decimal("1"), numbers.Real))Результат: True, True, True, True, False.
Задания
- Посчитайте сумму
0.1сто раз черезfloatиDecimal, сравните результаты. - Реализуйте функцию округления цены до копеек с режимом «банковского» округления и «школьного».
- Преобразуйте десятичную периодическую дробь
0.(3)вFractionи сложите с1/6.
