Использование модуля decimal в Python

Использование модуля decimal в Python Статьи

Подпишись на мой канал в Telegram

В данном руководстве мы рассмотрим использование модуля для работы с десятичными числами, который включен в стандартную библиотеку Python.

Введение

В Python есть числовые типы данных, такие как int, float и комплексные числа, но из-за машинной зависимости чисел с плавающей точкой нам нужен более точный тип данных для вычислений, требующих высокой точности. В этой статье мы рассмотрим модуль decimal в Python, который реализует десятичные числа с точностью до 28 цифр.

Использование

Python реализует десятичные числа как числа двойной точности с плавающей точкой, которые зависят от машины. Для вычислений, где точность критична для бизнеса, числа с плавающей точкой могут вызывать ошибки при выполнении на другой машине. Поэтому для таких приложений нам нужен независимый от машины тип данных для реализации десятичных чисел, который был реализован с помощью модуля decimal в Python. Кроме того, модуль decimal реализует десятичное число с точностью до 28 десятичных цифр, в то время как числа с плавающей запятой имеют точность до 18 цифр.

Это можно наблюдать в следующем примере

import decimal

float_num = 100 / 3
print(float_num)
decimal_num = decimal.Decimal(100) / decimal.Decimal(3)
print(decimal_num)

Вывод программы

33.333333333333336
33.33333333333333333333333333

Вторая причина использования десятичных чисел вместо чисел с плавающей точкой заключается в том, что в Python числа не могут быть представлены с использованием их точного значения, а используется только приближение, что может быть опасно для критически важных программ.

Из-за аппроксимации значения с плавающей точкой дают разные результаты для разных вычислений. Например, если мы сложим 1,2 и 2,2, используя значения с плавающей точкой, ответ должен быть равен 3,4. Но когда мы сравним добавленное число и 3,4, они не будут равны. Эта ошибка возникает из-за приближений в числах с плавающей запятой, из-за которых сумма 1,2 и 2,2 не равна 3,4.

Поэтому в случаях, когда необходимо сравнить десятичные значения, следует использовать десятичный модуль, а не числа с плавающей точкой.

Это может быть более понятно из следующего примера.

a = 1.2
b = 2.2
c = 3.4
d = a + b
print("a:", a)
print("b:", b)
print("c:", c)
print("a+b:", d)
print("a+b==c?:", d == c)

Вывод программы

a: 1.2
b: 2.2
c: 3.4
a+b: 3.4000000000000004
a+b==c?: False

Настройка контекста

Чтобы использовать модуль decimal в Python, достаточно его импортировать следующим образом.

import decimal

Импортированный модуль имеет предопределенный контекст, который содержит значения по умолчанию для точности, округления, флагов, минимально и максимально допустимых чисел. Мы можем посмотреть значения контекста с помощью метода getcontext() следующим образом.

import decimal

print(decimal.getcontext())

Вывод программы

Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

Мы также можем установить точность и другие параметры контекста. Чтобы изменить точность на 2 цифры вместо 28, мы можем использовать следующую программу.

import decimal

decimal.getcontext().prec = 2
print(decimal.getcontext())

Вывод программы

Context(prec=2, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

По умолчанию, при округлении десятичных чисел с помощью модуля decimal, числа округляются равномерно. Мы можем изменить это поведение, изменив значение «rounding» в контексте следующим образом.

import decimal

decimal.getcontext().rounding = "ROUND_HALF_DOWN"
print(decimal.getcontext())

Вывод программы

Context(prec=28, rounding=ROUND_HALF_DOWN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

Все арифметические операции над десятичными числами, определяемые модулем decimal, аналогичны операциям над числами с плавающей запятой. Разница заключается в точности значений из-за различий в реализации.

Округление значений

Мы можем округлять числа до определенных цифр с помощью функции round(). Функция round принимает десятичное число, которое нужно округлить, в качестве первого аргумента и количество цифр, до которых его нужно округлить, в качестве второго аргумента и возвращает округленное десятичное значение следующим образом.

import decimal

num1 = decimal.Decimal(100)
num2 = decimal.Decimal(3)
print("Первое число:", num1)
print("Второе число:", num2)
num3 = num1 / num2
print("Первое число разделенное на второе число:", num3)
num4 = round(num3, 2)
print("Округленное число:", num4)

Вывод программы

Первое число: 100
Второе число: 3
Первое число разделенное на второе число: 33.33333333333333333333333333
Округленное число: 33.33

Сравнение десятичных чисел

Как было показано в одном из разделов выше, сравнение чисел с плавающей запятой может привести к неправильным результатам, но десятичные числа являются точными, и их сравнение всегда даст желаемый результат. Это можно увидеть следующим образом.

import decimal

a = decimal.Decimal("1.2")
b = decimal.Decimal("2.2")
c = decimal.Decimal("3.4")
d = a + b
print("a:", a)
print("b:", b)
print("c:", c)
print("a+b:", d)
print("a+b==c?:", c == d)

Вывод программы

a: 1.2
b: 2.2
c: 3.4
a+b: 3.4
a+b==c?: True

В приведенном выше коде видно, что мы преобразовали строки в десятичные числа вместо того, чтобы преобразовывать числа с плавающей точкой в десятичные. Это сделано потому, что если мы преобразуем число с плавающей точкой в десятичное, то ошибка аппроксимации распространится на десятичное число, и мы не получим желаемого результата.

Заключение

В этой статье мы изучили недостатки выполнения арифметических операций с числами с плавающей точкой и использовали модуль decimal для реализации тех же операций без ошибок в Python. Мы также можем написать программы, использованные в этой статье, с обработкой исключений, используя python try except, чтобы сделать программы более надежными и систематически обрабатывать ошибки.

Оставайтесь с нами для получения новых информативных статей.

close

Бесплатная подписка

Введи свой адрес электронной почты и получай моментальный доступ к новым публикациям на сайте

Вступи в мою группу ВКонтакте

Егор Егоров

C 2017 года сижу на игле Python. Люблю создавать контент, который помогает людям понять сложные вещи. Не представляю жизнь без спорта и чувства юмора.

Если не сложно, напиши комментарий, как тебе статья.

Оцените автора
Егоров Егор
Добавить комментарий

  1. Андрей

    Автор Молодец….статья интересная ….продолжай писать подобное )))

    Ответить
  2. Андрей

    Всё доходчиво понятно….с примерами с докозательствами …циры наглядно подтверждают эфективность данной программы !

    Ответить