Доброго времени суток, читатели, зрители моего канала programmer's notes. Не забывайте подписываться и писать свои комментарии к моим статьям и видео.
Модуль decimal и работа с вещественными числами на Python
Хотя термин 'вещественный' является не точным, по отношению к числам, которые используются в программировании с точки зрения математики, я считаю этот термин подходящим. Следует рассматривать его как термин программирования, а не как термин математический.
Числовой тип float в Python основывается на вычислениях на основе возможностей процессоров. Использование float в вычислениях несёт в себе три проблемы:
1. Одна и та же программа, которая будет выполняться на разных компьютерах, с процессорами, несколько отличающимися друг от друга, может давать для вычисления с вещественными числами несколько разные значения.
2. Обычные числа с конечным числом разрядов после запятой в десятичном формате не всегда могут быть точно представлены в двоичном виде. А именно так и представляются вещественные числа в процессоре. Отсюда возникающая погрешность вычислений.
3. Точность float ограничена восемнадцатью знаками после запятой.
В связи вышеперечисленными проблемами, есть потребность иметь библиотеку, которая бы была лишена этих проблем. Вот библиотека decimal призвана дать в руки программистов более точный инструмент вычислений.
Модуль decimal работает очень просто. Есть набор начальных настроек, который можно получить так
#!/usr/bin/python3
import decimal as dc
print(dc.getcontext())
Результат работы фрагмента
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
Настройки можно менять
decimal.getcontext().prec = 6 # меняем точность вычислений
Пример 1.
#!/usr/bin/python3
import decimal as dc
a = dc.Decimal('1')
b = dc.Decimal('7')
c = a / b
print(c)
Результат выполнения
0.1428571428571428571428571429
Выделим один важный момент. Модуль decimal даёт точный результат лишь в пределах заданной точности.
Пример 2. Для float
#!/usr/bin/python3
a = 1.2
b = 2.2
c = a + b
print(c)
Результат выполнения
3.4000000000000004
Да именно так и результат обусловлен тем, о чём я сказал выше: выполнения действий в двоичном формате.
Пример 3.
#!/usr/bin/python3
import decimal as dc
a = dc.Decimal('1.2')
b = dc.Decimal('2.2')
c = a + b
print(c)
Результат выполнения
3.4
Важное замечание. Число следует помещать в кавычки для того, чтобы оно сразу преобразовывалось бы в тип Decimal. Если написать Decimal(1.2), то число в начале будет представлено в формате float, а, следовательно, может быть потеряна точность, ещё до того момента, как произойдёт преобразование к decimal.
Модуль decimal довольно богат разными методами. Среди них есть и встроенные функции: Decimal.sqrt() - квадратный корень, Decimal.log10() - десятичный логарифм, Decimal.ln() - натуральный логарифм, Decimal.exp() - экспонента. Есть также множество других функций, которые я здесь перечислять не буду. Конечно, можно использовать и функции библиотеки math, но в этом случае произойдет преобразование числа к типу float.
Пример 4.
#!/usr/bin/python3
import decimal as dc, math
a = math.sin(dc.Decimal('2'))
print(a)
print(type(a))
Результат выполнения
0.9092974268256817
<class 'float'>
Округление можно осуществлять обычной стандартной функцией round() языка Python
Пример 5.
#!/usr/bin/python3
import decimal as dc
a = dc.Decimal('2.24527809')
b = round(a, 2)
print(b)
print(type(b))
Результат выполнения
2.25
<class 'decimal.Decimal'>
Т.е. тип данных при этом не изменился.
Но библиотека decimal имеет и свой метод округления.
Пример 6.
#!/usr/bin/python3
import decimal as dc
a = dc.Decimal('2.24527809')
b = a.quantize(dc.Decimal('1.0000'))
print(b)
Результат выполнения
2.2453
Аргумент dc.Decimal('1.0000') означает, что округлять нужно до четырёх знаков после запятой. Сам же метод округления определяется установкой опции rounding. Работают следующие методы округления decimal.ROUND_CEILING, decimal.ROUND_DOWN, decimal.ROUND_FLOOR, decimal.ROUND_HALF_DOWN, decimal.ROUND_HALF_EVEN, decimal.ROUND_HALF_UP, decimal.ROUND_UP, decimal.ROUND_05UP.
Пример 7.
#!/usr/bin/python3
import decimal as dc
dc.getcontext().rounding = dc.ROUND_DOWN
a = dc.Decimal('20.24527809')
b = a.quantize(dc.Decimal('1.0000'))
print(b)
Результат выполнения
20.2452
Хорошего программирования. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.