Поиск по сайту:

Как выполнить точные десятичные вычисления с помощью Python?


В этой статье мы научимся выполнять точные десятичные вычисления в Python.

Используемые методы

  • Использование функции Decimal() модуля decimal

  • Использование функции fsum() математического модуля

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

Пример

Следующая программа показывает неспособность целых чисел с плавающей запятой точно выразить все числа по основанию 10:

x = 4.2
y = 3.1
 
# printing the sum of both the variables
print("x + y =", x + y)
 
# checking if the sum is both the variables is equal to 7.3
print((x + y) == 7.3)

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

x + y = 7.300000000000001
False

Эти ошибки являются «особенностью» ЦП, лежащего в основе системы, и стандарта арифметики IEEE 754, который используется его модулем вычислений с плавающей запятой. Вы ничего не сможете сделать, чтобы предотвратить такие ошибки, если пишете свой код с использованием экземпляров с плавающей запятой, поскольку тип данных Python с плавающей запятой сохраняет данные, используя собственное представление.

Использование десятичного модуля даст вам большую точность за счет некоторого снижения производительности. Давайте посмотрим на это ниже.

Способ 1: использование функции Decimal() десятичного модуля.

Пример

В следующей программе показано использование функции Decimal() для выполнения точных десятичных вычислений:

# importing Decimal from decimal module
from decimal import Decimal
x = Decimal('4.2')
y = Decimal('3.1')
# printing the sum of both the variables
print("x + y =", x + y)
# checking if the sum is both the variables is equal to 7.3 using by passing the sum to the Decimal Function
print((x + y) == Decimal('7.3'))

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

x + y = 7.3
True

В приведенном выше коде на первый взгляд может показаться немного странным, например, указание чисел в виде строк. Тем не менее, десятичные объекты работают именно так, как вам хотелось бы (поддерживая все распространенные математические операции и т. д.). Они выглядят как обычные числа, когда вы их печатаете или используете в функциях форматирования строк.

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

Пример

Для этого создайте локальный контекст и измените его настройки.

# importing localcontext from decimal module
from decimal import localcontext
x = Decimal('2.3')
y = Decimal('2.7')
# dividing x by y(returns as a floating-point number)
print(x / y)
with localcontext() as context:
   # rounding the number upto 3 digits i.e, precision 3
   context.prec = 3
   # Dividing x by y with precision set to 3
   print(x / y)

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

0.8518518518518518518518518519
0.852

Увеличение значения точности до «60» для более высокой точности.

Пример

# importing localcontext from decimal module
import decimal
from decimal import localcontext
x = decimal.Decimal('2.3')
y = decimal.Decimal('2.7')
# dividing x by y(returns as a floating-point number)
print(x / y)
with localcontext() as context:
   # Rounding the number upto 60 digits i.e, precision 60
   context.prec = 60
   # Dividing x by y with precision set to 3
   print(x / y)

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

0.8518518518518518518518518519
0.851851851851851851851851851851851851851851851851851851851852

Способ 2. Использование функции fsum() математического модуля.

Десятичный модуль реализует «Общую спецификацию десятичной арифметики» IBM.

Само собой разумеется, что существует множество вариантов настройки, выходящих за рамки этой статьи.

У новичков Python может возникнуть соблазн использовать модуль decimal, чтобы обойти проблемы с точностью данных типа float. Также важно знать область вашего приложения. Просто более типично использовать обычный тип с плавающей запятой при работе с научными или инженерными задачами, компьютерной графикой или большинством других задач научного характера.

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

Пример

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

inputList = [1.23e+18, 1, -1.23e+18]

# observe how the 1 disappears here if we perform sum() on the list
print(sum(inputList)) 

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

0.0

fsum() находит сумму между заданным диапазоном или итерацией. Требуется импорт математической библиотеки. Его широко используют в математических расчетах.

Синтаксис

Ниже приведен синтаксис функции.

maths.fsum( iterable )

Итерируемый объект может быть диапазоном, массивом или списком.

Тип возвращаемого значения –

Он возвращает число с плавающей запятой.

Пример

Следующий пример можно использовать для более точной реализации в math.fsum()

# importing math module 
import math
# input list
inputList = [1.23e+18, 1, -1.23e+18]
# adding the sum of elements of the list using the fsum() function
print(math.fsum(inputList))

Выход

При выполнении вышеуказанная программа сгенерирует следующий вывод:

1.0

Напротив, вам действительно необходимо изучить и понять свойства распространения ошибок других алгоритмов.

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

Таким образом, десятичный модуль предлагает возможность избежать этого. Когда Python взаимодействует с базами данных, объекты Decimal часто встречаются снова, особенно при доступе к финансовым данным.

Заключение

В этой статье мы узнали, как обычные вычисления не работают в определенных случаях и почему нам нужны правильные десятичные вычисления. Мы научились выполнять точные десятичные вычисления с помощью двух отдельных функций: decimal() и fsum(). Мы также узнали, как использовать функцию localcontext() для установки точности результата.

Статьи по данной тематике: