Micha Roon
Micha Roon

Reputation: 4007

Kotlin BigDecimal multiplication wrong results

I need to use BigDecimal for some computation but am a bit surprised by the behaviour:

val thousand = BigDecimal(1000)
val fee = BigDecimal(0.005)
println(thousand * fee)

You'd expect the console to contain 5 but the result is 5.000000000000000104083408558608425664715468883514404296875000

I know that I can limit the precision and do some rounding with setScale but the real question is Why is this needed in the first place. This result is obviously wrong.

What am I missing?

Upvotes: 0

Views: 701

Answers (1)

user31601
user31601

Reputation: 2610

The issue is likely to be with the construction of the fee BigDecimal. This is taking a double value and converting it to a BigDecimal. Unfortunately, some fairly simple decimal fractions are impossible to precisely represent as doubles or floats, and this constructor for BigDecimal will take that imprecise double as its value.

From the documentation:

The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.

The way around this is to use the String constructor, which gets round the issue of having to convert "via" a double.

Upvotes: 2

Related Questions