What is the standard library to use when dealing with money in Kotlin?

I am trying to represent the value of money that supports other currencies and conversion between them and has 100% precision in mathematical operation. Is it better to build an implementation to represent money from the ground up or is there a standard library to use?

You mean conversion like dollars to cents or dollars to euros? The first is usually performed by using BigDecimal (Java only) or simply integers and representing values in the “smallest” currency. The second requires some kind of an internet service.

I mean a type that represents monetary values. I would assume some standard libraries are used for monetary representation as there would be precision issues when doing operations, no?

I think generally most apps represent currency as an integer value. My company has an internal Money class which is just a BigInteger (representing the amount) and the currency type.

1 Like

Thank you for the help. How do you deal with the decimal values without having issues with precision?

I said this already. Either BigDecimal or integers using the smallest currency. There are no hidden corner cases or anything otherwise tricky here.

This JUnit test fails:

@Test
fun test_decimal_() {
    assertEquals((BigDecimal(0.01) + BigDecimal(0.06)), BigDecimal(0.07))
}

When a user receives some money, I want the values to be exact, hence my original question. My app is a budgeting tool, but I still value precision for scenarios like these.

You need to use the String consturctor:
BigDecimal("0.01")

Also, I suggest not using equals() and instead use compareTo() == 0. It would work in this case, it wouldn’t if scale is different.

This JUnit test brakes in your case:

@Test
fun test_bin() {
   assertEquals((BigDecimal("1") / BigDecimal("3")), BigDecimal("0.33"))
}

Because that’s incorrect. 1/3 = 0.33333333…, not “0.33”. If you want rounding, you need to specify rounding.

The issue isn’t with the equals, it is with the fact the addition fails.

If you ran the example, you would get 0 for the result:
This JUnit test also fails:

@Test
fun test_bin() {
   assertEquals((BigDecimal("1") / BigDecimal("4")), BigDecimal("0.25"))
}

(You are right about the division, and I thought the assert would do the rounding for me)

Just do: assertEquals((BigDecimal("1.00") / BigDecimal("4.00")), BigDecimal("0.25")). But most importantly: read the documentation for BigDecimal if you plan to use it.

2 Likes

This works. Thank you for the help.