How should I best store fixed point Decimal values in Python for cryptocurrency?
decimal, django, python
Solution
You can safely use Decimal instead. It is really decimal under the hood, i.e. there are no base-conversion errors. If you store
import decimal
d = decimal.Decimal('4.10500008')
there will be no loss of precision.
Just make sure you create the numbers by using strings, because otherwise you'll have trouble:
>>> decimal.Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
versus:
>>> decimal.Decimal('1.1')
Decimal('1.1')
One more important thing to understand is that `decimal.Decimal` carries the precision, as well:
>>> decimal.Decimal('1.10')
Decimal('1.10')
This is very useful with financial applications.
For more information, see: https://docs.python.org/2/library/decimal.html
N.B. As `Mark Dickinson` reminds below, the `decimal` module does not use arbitrary precision, the number of significant numbers in calculations is limited. This limit can be set or queried by `decimal.getcontext().prec`, and the default value is 28. The default value should be quite enough for usual financial calculations (down to billionth of cents in the US state debt), but if you need more, you may set it to a larger number.
Problem
I'm playing around with developing a Django/Python app which stores, and does calculations on, cryptocurrency values. These are decimal values to 8 decimal places, eg, 0.00000008, 4.10500008, 6000.00000000. Perhaps partly from not being confident fully in the nuances of how Python's Decimal works, and partly on advice I've seen for different languages, I was thinking it might be safer to store values as their satoshi equiv values in an BigInteger field, eg for 0.00000008 I store 8, for 4.10500008 I store 410500008 and for 6000.00000000 I store 600000000000. Is this a good idea or should I be using Decimal with some particular setting instead? Thanks!