For a custom build, refer to INSTALL.txt. For a Windows build, see vcbuild\README.txt.
# Unix: ./configure make sudo make install
# Unix: cd examples gcc -Wall -W -O2 -o pow pow.c -l:libmpdec.so.2 -lm # Try a couple of values: ./pow 2 1234567 4.9963964863286026867472463500015498863E+371641 Inexact Rounded
As for every C extension, the build requires a working C compiler. For most Linux distributions, the Python header files have to be installed explicitly, since they are shipped as a separate package:
# Debian, Ubuntu: sudo apt-get install gcc make sudo apt-get install python-dev # Fedora, RedHat: sudo yum install gcc make sudo yum install python-devel # openSUSE: sudo zypper install gcc make sudo zypper install python-devel # BSD: # You know what to do. # Mac OS X: # Install Xcode and Python headers.
If pip is present on the system, installation should be as easy as:
pip install cdecimal
tar xvzf cdecimal-2.3.tar.gz cd cdecimal-2.3 python setup.py install
If problems arise, read the file PYINSTALL.txt which comes with the distribution.
The easiest way is to use the binary installers. Otherwise, the build requires Visual Studio.
Showing off cdecimal’s bignum speed. Note that the factorial function is entirely written in Python and does not call a C factorial function.
from cdecimal import * def _factorial(n, m): if (n > m): return _factorial(m, n) elif m == 0: return 1 elif n == m: return n else: return _factorial(n, (n+m)//2) * _factorial((n+m)//2 + 1, m) def factorial(n): return _factorial(n, 0) c = getcontext() c.prec = MAX_PREC # 1000000! in pure Python x = factorial(Decimal(1000000)) sx = str(x) # Compare to Python integers: y = factorial(1000000) sy = str(y)
Showing off cdecimal’s speed for small precisions. Again, the algorithm is in pure Python and does not involve calling a custom C pi-function. This is also the benchmark where cdecimal is often faster than Java’s BigDecimal.
import cdecimal import decimal def pi(module, prec): """From the decimal.py documentation""" module.getcontext().prec = prec + 2 D = module.Decimal lasts, t, s, n, na, d, da = D(0), D(3), D(3), D(1), D(0), D(0), D(24) while s != lasts: lasts = s n, na = n+na, na+8 d, da = d+da, da+32 t = (t * n) / d s += t module.getcontext().prec -= 2 return +s for i in range(10000): x = pi(cdecimal, 28) for i in range(10000): y = pi(decimal, 28)
The telco benchmark was devised by Mike Cowlishaw as a way of measuring decimal performance in a real world telecom application.
# decimal.py python telco.py # sanity check python telco.py full # benchmark # Edit telco.py and change decimal to cdecimal. # Speedups should be about 30x. python telco.py # sanity check python telco.py full # benchmark
This is a nice tip from the sqlalchemy developers. Since cdecimal.Decimal currently does not support mixed operations with decimal.Decimal, the easiest way to enforce global use of cdecimal is to occupy both places for cdecimal and decimal in sys.modules. This must take place at program start, before importing anything else.
This technique is used in the following section in the file psycopg.py.
# At program start: import sys import cdecimal sys.modules["decimal"] = cdecimal # Further imports: import psycopg2 # psycopg2 imports cdecimal, masquerading as decimal from decimal import * # same here, this is now cdecimal ...
The PostgreSQL database adapter psycopg supports PostgreSQL’s numeric type. For a speed comparison, download setup_dectest.sql and psycopg.py. Naturally, both PostgreSQL and psycopg2 are required for this benchmark.
The benchmark inserts 100000 rows containing numeric data into the test database. Subsequently, it fetches all rows. Since INSERT has a lot of database overhead, the main speed gains are in FETCHALL. Similar speed gains (10x) have also been reported by Informix database users.
# Setup a test database: psql < setup_dectest.sql # Run the benchmark for decimal.py: python psycopg.py # Edit psycopg.py and uncomment the top two import lines to # use cdecimal globally. # The speedup should be about 1.7x for INSERT and 12x for FETCHALL. python psycopg.py