python-nicefloat is a Python module implementing an algorithm based on the paper "Printing Floating-Point Numbers Quickly and Accurately", by Robert G. Burger and R. Kent Dybvig.
The implemented algorithm will find the shortest, correctly rounded output string representing a decimal number that converts to the same internal binary floating-point number when read.
Static method returning a short and correctly rounding string:
>>> from nicefloat import nicefloat >>> f = 1.1 >>> print repr(f) 1.1000000000000001 >>> print str(f) 1.1 >>> print nicefloat.str(f) 1.1 >>> print float(repr(f)) == f True >>> print float(str(f)) == f True >>> print float(nicefloat.str(f)) == f True
Static method returning a not-so-short and correctly rounding string:
>>> f = 3.0/11 >>> print repr(f) 0.27272727272727271 >>> print str(f) 0.272727272727 >>> print nicefloat.str(f) 0.2727272727272727 >>> print float(repr(f)) == f True >>> print float(str(f)) == f False >>> print float(nicefloat.str(f)) == f True
Using it as a numeric type is possible as well:
>>> f = 1.1 >>> f 1.1000000000000001 >>> f*2 2.2000000000000002 >>> f = nicefloat(1.1) >>> f 1.1 >>> f*2 2.2 >>> -1.1+f*2 1.1 >>> type(-1.1+f*2) <class 'nicefloat.nicefloat'> >>> isinstance(nicefloat(1.1), float) True
This is not decimal arithmetic
This module is about a shorter decimal representation for binary floating point numbers. It's not a module for decimal floating point arithmetic.
If you're looking for decimal floating point arithmetic in Python, check the decimal module.
Why not str()?
Because str() truncates the floating point number. In other words,
>>> f = 1.1000000000000002 >>> float(str(f)) == f False
Why not repr()?
If you're happy with the repr() result for floats, use it. It's certainly faster.
Why nicefloat.str(1.1*3) is still 3.3000000000000003?
Because that's the appropriate form to represent the result of that operation. If you were expecting a result like 3.3, you'll probably be surprised to see the following:
>>> 1.1 1.1000000000000001 >>> 1.1*3 3.3000000000000003 >>> 3.3 3.2999999999999998 >>> 1.1*3 == 3.3 False
If you really want to see 1.1*3 == 3.3, you're looking for decimal floating point arithmetic.
python-nicefloat is available under the LGPL.
Gustavo Niemeyer <email@example.com>