Эмуляция фиксированной точности в Python
Для университетского курса по численному анализу мы переходим от Maple к комбинации Numpy и Sympy для различных иллюстраций материала курса. Это потому, что студенты уже изучают Python семестр раньше.
Одна из трудностей, с которыми мы сталкиваемся, заключается в эмуляции фиксированной точности в Python. Maple позволяет пользователю указывать десятичную точность (скажем, 10 или 20 цифр), и с этого момента каждый расчет выполняется с такой точностью, чтобы вы могли видеть эффект ошибок округления. В Python мы попробовали несколько способов добиться этого:
- Sympy имеет функцию округления до указанного числа цифр.
- Mpmath поддерживает пользовательскую точность.
Это, однако, не то, что мы ищем. Эти параметры вычисляют точный результат и округляют точный результат до указанного количества цифр. Мы ищем решение, которое делает каждый промежуточный расчет с заданной точностью. Что-то, что может показать, например, ошибки округления, которые могут произойти при делении двух очень маленьких чисел.
Наилучшим решением на данный момент являются пользовательские типы данных в Numpy. Используя float16, float32 и float64, мы смогли хотя бы дать представление о том, что может пойти не так. Проблема здесь в том, что нам всегда нужно использовать массивы из одного элемента и что мы ограничены этими тремя типами данных.
Существует ли что-то более гибкое для нашей цели? Или то, что мы ищем, спрятано где-то в документации mpmath? Конечно, есть обходные пути, заключающие каждый элемент вычисления в функцию округления, но это скрывает код для студентов.
1 ответ
Ты можешь использовать decimal
, Есть несколько способов использования, например, localcontext
или же getcontext
,
Пример с getcontext
из документации:
>>> from decimal import *
>>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7)
Decimal('0.142857')
Пример localcontext
использование:
>>> from decimal import Decimal, localcontext
>>> with localcontext() as ctx:
... ctx.prec = 4
... print Decimal(1) / Decimal(3)
...
0.3333
Чтобы уменьшить объем ввода, вы можете сократить конструктор (пример из документации):
>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')