In python3, I mainly use float or np.float32/64 and when it comes to store it into a database, even if SQL type is Numeric/Decimal we end up with 0.400000000000021 or something like that instead of 0.4
It may be a problem if such data is accessed from another application.
Working only with decimal.Decimal in python isn't an answer for us, since we heavely make use of pandas, and Decimal is not supported.
A solution would be to cast float to Decimal just before inserting into SQL (SQL Server in our case but it's a detail). And then back from Decimal to float after SELECT.
Do you have another (and nicer) way to handle such issue ?
The problem is that the value of your float isn't 0.4, because there is no value in either float32
or float64
(or Python native float
, which is usually the same as float64
) that's 0.4. The closest float64
to 0.4 that is 0.400000000000021, which is exactly what you've got.
Since that's the closest float
value there is to 0.4, if you ask Python to convert it to a string (e.g., print(f)
), it'll be friendly and give you the string 0.4
.
But when you pass it to a database… Well, it actually depends on which database interface library you're using. With some, it will call repr
, which would give you '0.4'
(at least in Python 3.x), so you're asking the database to store the float value of the string '0.4'
. But with others, it will pass the float value directly as a C double
, so you're asking the database to store the float value 0.400000000000021
.
So, what should you do?
Decimal
or float80
or decimal64
or some other type? Then you almost certainly want to set a SQL data type like DECIMAL(12, 6)
that matches your actual precision, and let the database take care of it. (After all, there is no difference between 0.4
rounded to 6 decimal places and 0.400000000000021
rounded to 6 decimal places.)Seriously, if the other code that's going to use this database is just going to read the values as float64
, or read them as strings and convert them to float64
(or float32
), they are going to end up with 0.400000000000021
no matter what you do, so don't do anything.
Also, consider this: if the difference between 0.4
and 0.400000000000021
is going to make any difference for any of your code, then your code is already broken by using float64
, before you even get to the database.