Floating Point Numbers

Floating point numbers are represented as the float type in Python. Physically, they are represented as base two (binary) fractions. As a result, certain fractions cannot be represented accurately, but merely as approximations. For more details, see the Python documentation on floating point numbers.

In [1]:
1.1 + 1.1
Out[1]:
2.2
In [2]:
1.1+1.2
Out[2]:
2.3
In [3]:
.1+.1
Out[3]:
0.2
In [1]:
.1+.2
Out[1]:
0.30000000000000004

As you can see, most of the math operations above behave as you would expect. However, from ".1 + .2", the inaccuracy of floating point arithmetic is apparent. For general applications, there isn't much of a concern for this inaccuracy isn't much of a concern. But when you are dealing with money or long running calculations, the small inconsistencies can become a large problem. In Python, this can be circumvented by utilizing the decimal module. The decimal module accurately handles floating point arithmetic without the limitations of base 2 fractions. You can use the decimal module like the following:

In [4]:
from decimal import *
Decimal('.1') + Decimal('.2')
Out[4]:
Decimal('0.3')

Notice that we import all (*) of the decimal module for use. We give the module a string representation of the number and use arithmetic operators as if Decimal was a number. This yields a Decimal with the correct result.

Apart from overcoming limitations of floating point arithmetic, the decimal module will calculate the result to a defined precision (20 decimal places by default) and round. Look at the examples below. The normal operation of "2/3" yields .6666 repeating, but does not get rounded to .666666666667 when the repeating decimal gets cut off. The decimal module will automatically round without you having to do so explicitly.

In [7]:
2/3
Out[7]:
0.6666666666666666
In [5]:
Decimal("2") / Decimal("3")
Out[5]:
Decimal('0.6666666666666666666666666667')

Don't want 20 points of precision? You can change that like so:

In [7]:
getcontext().prec = 4
Decimal("2") / Decimal("3")
Out[7]:
Decimal('0.6667')

Notice that the data type of our result is a Decimal object. If you want to cleanly output this for the user or use it as a number in a different kind of calculation or conditional, you can convert it like so:

In [8]:
float(Decimal("2") / Decimal("3"))
Out[8]:
0.6667
In [9]:
str(Decimal("2") / Decimal("3"))
Out[9]:
'0.6667'
In [10]:
int(Decimal("2") / Decimal("3"))
Out[10]:
0