mxNumber - Version 0.2.0
Python Interface to GNU MP Number Types
As you all know, Moshe Zadka has been pushing for a new rational number type recently (at the conference) and also implemented a proof- of-concept implementation of his rational PEP 239.
Since the GNU Multi-Precision Lib (GMP) already has all these tools providing what people want most when it comes to numbers (precision and speed), I thought that wrapping these as Python types would be a good idea. I know that Alex Martelli has been working on a similar approach, but that project (gmpy) seems to be inactive.
Anyway, even though the GMP is available for most Unix platforms and MacOS, there was no relyable port for Windows. This was a show- stopper for me, so I decided to port GMP to Windows, which was harder than I thought, but well, it's done now.
There's still no web-page for this package, so I'm providing the needed information in this posting.
WHAT'S NEW ? ------------
The 0.2.0 release is an alpha release. Everything is still in flux, so expect bugs, strange behaviour etc.
Still, the package provides some interesting insights into the issues you run into when dealing with computational representations of numbers. For now, you should consider the package a pure fun-package and playground for experiments.
New in this release are a parser for rational strings (formats "1/2" and "3 1/3"), plus a new constructor FareyRational() which was inspired by an algorithm written by Scott David Daniels and posted to the Python Cookbook; see http://www.activestate.com/ASPN/Python/Cookbook/Recipe/52317
The FareyRational() constructor allows you to convert floating point numbers to rationals, e.g. 1.3333 to 4/3.
The package is part of the eGenix.com EXPERIMENTAL package and called mx.Number. It provides access to three numerical types:
1. Integer(value) -- arbitrary precision integers much like Python long only faster 2. Rational(nom,denom) -- rational numbers with Integers as numerator and denominator 3. Float(value[,prec]) -- floating point number with at least prec bits precision 4. FareyRational(value, maxden) -- calculate the best rational represenation n/d of value such that d < maxden
* GMP 3.1.1 - Unix: GMP 3.1.1 must be installed (http://www.swox.com/gmp/) - Windows: GMP 3.1.1 is included in the download archives for Windows
* Python 2.1
* Optional: egenix-mx-base package available from http://www.lemburg.com/files/python/
* The "egenix-mx-experimental" package which includes mx.Number:
Source: http://www.lemburg.com/files/python/egenix-mx-experimental-0.2.0.zip RPM: http://www.lemburg.com/files/python/egenix-mx-experimental-0.2.0-1.i386-py2.... Windows installer: http://www.lemburg.com/files/python/egenix-mx-experimental-0.2.0.win32-py2.1...
Usage is simple: ----------------
from mx.Number import * f = Float(3.141) r1 = Rational(3.141) r2 = Rational(2, 3) r3 = FareyRational(1.33333, 1000) i = Integer("1231231231231231231231231")
The coercion model will (someday) look like this:
Float ^ | --------> Python float | ^ | | | Rational | ^ | | Python long -----> Integer ^ ^ | | -------- Python integer
Complex numbers are not integrated into the picture since I think that they should not be auto-coerced.
Some of these arrows are not implemented yet, others are not shown (e.g. Integer(2) + "3" works as one would expect ;-).
Note that this is still a very rough version. Feedback is welcome.
* What do you think about this coercion model ? Shouldn't we have a PEP for this ?
* Please try out the rational type and see if it fits your needs -- the results are sometimes surprising (due to the IEEE representations of floats); I'm sure this proof of concept will raise a few more questions regarding the usefulness of switching to rationals for literals like 1.123.
* This implementation also showed that even though the coercion patches have made integraton of numerical types easier, a full integration is still hard to achieve. Some issues:
- string formatting cannot be "overridden" to allow formatting of these new types
- there is no way of providing PyArg_ParseTuple() parser markers for the types
- there is no way to bind the types to a Python literal, e.g. by specifying a number literal modifier which is then bound to the type: 1234L -> long("1234"), 1234.123F -> Float("1234.123"), 2R / 3 -> Rational(2, 3) etc.