Ответ 1
Библиотека GMP является одной из лучших библиотек математики произвольной точности, и существует привязка Python, доступная в GMPY. Я бы попробовал этот метод.
Кто-нибудь знает о более быстрой десятичной реализации в Python?
Как показывает пример ниже, стандартное десятичное число в python примерно в 100 раз медленнее, чем float.
from timeit import Timer
def run(val, the_class):
test = the_class(1)
for c in xrange(10000):
d = the_class(val)
d + test
d - test
d * test
d / test
d ** test
str(d)
abs(d)
if __name__ == "__main__":
a = Timer("run(123.345, float)", "from decimal_benchmark import run")
print "FLOAT", a.timeit(1)
a = Timer("run('123.345', Decimal)", "from decimal_benchmark import run; from decimal import Decimal")
print "DECIMAL", a.timeit(1)
FLOAT 0.040635041427
DECIMAL 3.39666790146
Библиотека GMP является одной из лучших библиотек математики произвольной точности, и существует привязка Python, доступная в GMPY. Я бы попробовал этот метод.
Вы можете попробовать cdecimal:
from cdecimal import Decimal
Начиная с Python 3.3, реализация cdecimal теперь является встроенной реализацией модуля стандартной decimal
библиотеки, поэтому вам не нужно ничего устанавливать. Просто используйте decimal
.
Для Python 2.7 установка cdecimal
и использование его вместо decimal
должно обеспечивать ускорение, аналогичное тому, которое получает Python 3 по умолчанию.
Вам следует сравнить производительность Decimal с Long Integer, а не с плавающей запятой. Плавающая точка в большинстве случаев является аппаратной. Десятичное значение используется для десятичной точности, а плавающая точка - для более широкого диапазона. Используйте десятичный пакет для денежных расчетов.
Чтобы процитировать руководство по десятичным пакетам:
Десятичные числа могут быть представлены точно. Напротив, цифры типа 1.1 не имеют точного представления в двоичной плавающей запятой. Конечные пользователи обычно не ожидали, что 1.1 будет отображаться как 1.1000000000000001, как это происходит с бинарной плавающей точкой.
Точность переносится в арифметику. В десятичной плавающей точке "0,1 + 0,1 + 0,1 - 0,3" точно равна нулю. В двоичной с плавающей запятой результат равен 5.5511151231257827e-017. В то время как вблизи нуля, различия предотвращают надежное тестирование равенства и могут накапливаться различия. По этой причине десятичное значение было бы предпочтительнее в приложениях учета, которые имеют строгие инварианты равенства.
python Decimal очень медленный, можно использовать float или более быструю реализацию Decimal cDecimal.
Используйте cDecimal.
Добавьте в свой тест следующее:
a = Timer("run('123.345', Decimal)", "import sys; import cdecimal; sys.modules['decimal'] = cdecimal; from decimal_benchmark import run; from decimal import Decimal")
print "CDECIMAL", a.timeit(1)
Мои результаты:
FLOAT 0.0257983528473
DECIMAL 2.45782495288
CDECIMAL 0.0687125069413
(Python 2.7.6/32, Win7/64, AMD Athlon II 2.1 ГГц)