How to deal with rounding errors of floating types for financial calculations in Python SQLite?

StackOverflow https://stackoverflow.com/questions/1801307

  •  05-07-2019
  •  | 
  •  

Question

I'm creating a financial app and it seems my floats in sqlite are floating around. Sometimes a 4.0 will be a 4.000009, and a 6.0 will be a 6.00006, things like that. How can I make these more exact and not affect my financial calculations?

Values are coming from Python if that matters. Not sure which area the messed up numbers are coming from.

Was it helpful?

Solution

This is a common problem using SQLite as it does not have a Currency type.
As S.Mark said you can use the Decimal representation library. However SQLite 3 only supports binary floating point numbers (sqlite type REAL) so you would have to store the Decimal encoded float as either TEXT or a BLOB or convert to REAL(but then you'd be back to a 64bit binary float)
So consider the range of numbers that you need to represent and whether you need to be able to perform calculations from within the Database.

You may be better off using a different DB which supports NUMERIC types e.g. MYSql, PostgreSQL, Firebird

OTHER TIPS

Seeing as this is a financial application, if you only have calculations up to 2 or 3 decimal places, you can store all the data internally as integers, and only convert them to float for presentation purposes.

E.g.

6.00 -> 600
4.35 -> 435

Most people would probably use Decimal for this, however if this doesn't map onto a database type you may take a performance hit.

If performance is important you might want to consider using Integers to represent an appropriate currency unit - often cents or tenths of cents is ok.

There should be business rules about how amounts are to be rounded in various situations and you should have tests covering each scenario.

Use Decimal to manipulate your figures, then use pickle to save it and load it from SQLite as text, since it doesn't handle numeric types.

Finaly, use unitest and doctest, for financial operations, you want to ensure all the code does what it is suppose to do in any circonstances. You can't fix bugs on the way like with, let's say, a social network...

You have to use decimal numbers. Decimal numbers can be represented exactly.

In decimal floating point, 0.1 + 0.1 + 0.1 - 0.3 is exactly equal to zero. In binary floating point, the result is 5.5511151231257827e-017.

So, just try decimal:

import decimal
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top