← Назад к вопросам

Что такое Decimal?

1.0 Junior🔥 161 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Decimal?

Decimal — это модуль в Python, который предоставляет класс для работы с десятичными числами с произвольной точностью. Это альтернатива встроенному типу float, которая избегает проблем с неточностью при работе с дробными числами.

Почему нужен Decimal?

Базовый тип float использует двоичное представление (IEEE 754), что приводит к ошибкам округления:

# Проблема с float
result = 0.1 + 0.2
print(result)  # 0.30000000000000004 — неправильно!
print(result == 0.3)  # False

# Финансовые расчёты становятся опасными
price = 0.1
quantity = 3
total = price * quantity
print(total)  # 0.30000000000000004
print(total == 0.3)  # False

Решение: Decimal

from decimal import Decimal

# Decimal работает с точностью
result = Decimal('0.1') + Decimal('0.2')
print(result)  # 0.3 — правильно!
print(result == Decimal('0.3'))  # True

# Финансовые расчёты
price = Decimal('0.1')
quantity = 3
total = price * quantity
print(total)  # 0.3 — точно!

Как работает Decimal?

Decimal хранит числа в десятичной форме как строку символов (мантисса и экспонента), а не в двоичной:

from decimal import Decimal

# Создание Decimal
d1 = Decimal('3.14')  # Из строки — самый точный способ
d2 = Decimal(3.14)    # Из float — имеет погрешности
d3 = Decimal(314) / Decimal(100)  # Из операций

print(d1)  # 3.14
print(d2)  # 3.140000000000000124344978758017532527446746826171875
print(d3)  # 3.14

# Лучше всегда использовать строки!
print(Decimal('3.14') == Decimal(3.14))  # False

Контекст Decimal

Контекст определяет поведение Decimal (точность, режим округления и т.д.):

from decimal import Decimal, getcontext, ROUND_HALF_UP

# Получить текущий контекст
ctx = getcontext()
print(ctx.prec)  # 28 — дефолтная точность (28 цифр)

# Установить новую точность
getcontext().prec = 5
result = Decimal('1') / Decimal('3')
print(result)  # 0.33333 — 5 цифр точности

# Вернуть обратно
getcontext().prec = 28

# Установить режим округления
getcontext().rounding = ROUND_HALF_UP
result = Decimal('2.5').quantize(Decimal('1'))
print(result)  # 3 (округление к ближайшему чётному)

Операции с Decimal

from decimal import Decimal

# Арифметика
a = Decimal('10.5')
b = Decimal('3.2')

print(a + b)  # 13.7
print(a - b)  # 7.3
print(a * b)  # 33.60
print(a / b)  # 3.28125
print(a % b)  # 0.9
print(a ** 2)  # 110.25

# Сравнение
print(a > b)   # True
print(a == Decimal('10.5'))  # True
print(a != b)  # True

Практический пример: расчёт цены

from decimal import Decimal, ROUND_HALF_UP

def calculate_total(items):
    """
    Расчёт общей стоимости товаров
    
    Args:
        items: список кортежей (количество, цена за единицу)
    
    Returns:
        Decimal: общая стоимость с округлением до копеек
    """
    total = Decimal('0')
    
    for quantity, price in items:
        line_total = Decimal(str(quantity)) * Decimal(str(price))
        total += line_total
    
    # Округлить до 2 знаков (копейки)
    return total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)

# Использование
items = [
    (3, '10.99'),  # 3 шт по 10.99 руб
    (2, '15.50'),  # 2 шт по 15.50 руб
    (1, '0.01'),   # 1 шт по 0.01 руб
]

total = calculate_total(items)
print(f"Сумма: {total} руб")  # 62.99 руб

Когда использовать Decimal?

  1. Финансовые расчёты: зарплата, платежи, валюта
  2. Научные вычисления: если нужна высокая точность
  3. Бухгалтерия: требуется точность до копеек
  4. Работа с базами данных: NUMERIC, DECIMAL типы
# Пример из web приложения
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    # max_digits=10 означает всего 10 цифр
    # decimal_places=2 означает 2 знака после запятой
    # Максимальное значение: 99999999.99

Производительность

import timeit
from decimal import Decimal

# Decimal медленнее float
float_time = timeit.timeit(
    lambda: 0.1 + 0.2,
    number=1000000
)

decimal_time = timeit.timeit(
    lambda: Decimal('0.1') + Decimal('0.2'),
    number=1000000
)

print(f"float: {float_time:.4f}s")
print(f"Decimal: {decimal_time:.4f}s")
# Decimal обычно в 10-100 раз медленнее, но точнее

Вывод

Decimal — это:

  • Класс для работы с десятичными числами произвольной точности
  • Альтернатива float с избежанием ошибок округления
  • Обязателен для финансовых приложений
  • Медленнее float, но гораздо точнее
  • Всегда создавайте из строк, а не из float
  • Используйте контекст для управления точностью и округлением
Что такое Decimal? | PrepBro