Hello. QUick question. What should I be using to c...
# multiplatform
p
Hello. QUick question. What should I be using to calculate currency amounts? I found this, but I thought I’ll check if you have other suggestions. Thanks! https://github.com/ionspin/kotlin-multiplatform-bignum
k
Unless you're dealing with obscenely large numbers, you should be representing currency as a whole integer of the smallest subunit of a currency. For example, 1 USD would be represented as 100 US cents.
This avoids floating point imprecision on money.
p
@kevin.cianfarini Sadly, it still not as precise as expected. I already implemented it to multiply it to 100 first before calculating, but apparently, for example,
2.28 * 100 = 227.0
My current latest and quickest solution without using bignum is to instead convert the double to string and manually move the decimal point two places to the right, then parse it into integer.
z
You really do not want to use floating point values for money
k
What is the source of this
2.28
data?
p
a double
So, I was curious if it was a Kotlin Lang limit, or is an actual computer limit. I know Float/Double is not the best data type to use for currency, but the fundamentals of my app has been using that, so I have less time to do an overhaul. I'll still update it in the future, but I made some temporary changes for now. Anyway, upon testing this particular calculation, it turns out that 2.28 x 100 = 227.9999..., which is why I got 227 as an int. It didn't round it off, it only truncated the decimal amounts. This was a very, very edge case at this point. Our QA team has been testing a lot of stuff on the e-commerce module I made, and hasn't encountered anything like this. That's because I encountered this before when I "purely" used double as amount, but for calculations, I convert the double to int using
x 100
and do arithmetic. Since I encountered this, now I need to really do a big fix for this.
k
Floating point imprecision is part of the IEEE 754 spec. It's not a kotlin thing.
c
The point of what Kevin is saying is to not use the 2.28 at all. Don’t start with a Double and then convert to an Int, start with an Int. If you have a string, don’t do
"2.28".toDouble() * 100
, manually split the string on the decimal and convert to dollars and cents only as integers. The problem isn’t that
2.28 * 100
is lossy, it’s that you have the
2.28
value at all. The only safe way to work with currency is to use the same unit throughout all calculations. Floating-point values are always subject to loss of information (in other words, real-world money literally disappears or is generated), so you need to be using Integer-based calculations through every operation of the entire module. Even without converting to an Integer, FP-values by design can represent much higher numbers than integers, but they do so as the cost of losing precision