(Disclaimer: I don't work with any financial figures and I have not checked whether the dec64 proposal is a sound one.)
(Disclaimer: I don't work with any financial figures and I have not checked whether the dec64 proposal is a sound one.)
*Ok not that one.
In Python, the story looks slightly better:
from decimal import *
>>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7)
Decimal('0.142857')
But neither of these data types is even close to being a first class citizen in either language.But I think it's important to make sure programmers don't end up with the idea that they might as well store money amounts in binary floating point because the language they are using doesn't support decimal.
.getcontext().prec = 6
makes no sense for money. You need 2 digits after the decimal point constantly, whether it is 0.01 or 1000000.01AFAIK (and I don't do this for work), after every calculation you manually need to call quantize as in
cents = decimal.Decimal('.01')
money = price.quantize(cents, decimal.ROUND_HALF_UP)https://en.wikipedia.org/wiki/Decimal_data_type
Also, I don't try to endorse the Python API. I don't even use it. I just pointed out their api is easier since the operators work with their decimal data type, as opposed to the Java version.
In general you need to know when to round and to how many digits. But my complaint was that languages have a natural API for binary floating point, which is useful for scientific number crunching, but rarely anything comparable for commercial calculations.
I have not tried to design a natural API for fixed (but parameterizable) decimal precision and the implicit rounding required. But I would be surprised if it's impossible to come up with anything less verbose (explicit constructors everywhere) and less error prone (forgetting to call rounding).
If you're on the JVM, Groovy is nicer in that regard. It uses by default BigDecimal and BigInteger for literal numeric types, and has operator overloading: http://groovy-lang.org/syntax.html
Apache Groovy uses by default BigDecimal for literal decimal types, but only uses BigInteger for literal integral types when it would overflow the largest available primitive type for that literal. You can force a BigInteger by using the suffix `g` on the integral literal. Perhaps misunderstanding this is the source of some hard-to-find bugs in some of your Groovy code.
https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.ht...
I have never done any SW development in the commercial domain. Do you say in banking system the amounts never make it to the host language, they are always calculated in the database?
A cashier system most likely doesn't even have a database. At least not used for every item.
For the average cashier / checkout system I would doubt that, although again I have never seen the source.
That works fine for addition and subtraction. When you divide (or do percent calculations) integer cents is no longer, you need to deal with rounding manually/some custom class with every calculation.
Also, what's with the aversion to traits/types? This is the whole point of having operators/types.
We need a decimal format because people who read the code are sometimes not coders how know about the various tricks to pack decimals in uint64.
So, u64 is perfectly doable, sure, but it doesn't scale with the various types of people who write/read the code.
(same thing for floats : you can do money computations with them, but that'll work only if the people understand the trade offs of the representation; and believe me, they're not legions)
It’s provided in most higher level environments these days (java, .net - where I think it might even be a vm primitive?)
I still question the value of it but it does allow “perfect” representation of values common in decimal systems. But by the same token it can’t represent everything in all other bases. Shrug.