Search code examples
javakotlinbigdecimal

java.math.BigDecimal division inaccuracy


In Kotlin, BigDecimal division returns strange results.

BigDecimal(1.0) / BigDecimal(2.0)
// returns 0.0
// Just like Int(1) / Int(2) returns 0

But:

BigDecimal(1.1) / BigDecimal(2.0)
// returns 0.55
// Just like Double(1.1) / Double(2.0) returns 0.55

So why does that happen and how can I make 1.0 / 2.0 returns 0.5 with BigDecimal without using divide() giving a scale parameter?

UPDATES:

Here are the complete codes:

Welcome to Kotlin version 1.2.41 (JRE 1.8.0_172-b11)
Type :help for help, :quit for quit
>>> import java.math.BigDecimal
>>> BigDecimal(1.0) / BigDecimal(2.0)
0
>>> BigDecimal(1.1) / BigDecimal(2.0)
0.550000000000000044408920985006261616945266723632812

UPDATES 2:

According to @user2864740

BigDecimal(1.0).divide(BigDecimal(2.0))
// returns 0.5

and

BigDecimal("1.0") / BigDecimal(2.0)
// returns 0.5

So the results are confusing. For BigDecimals, why do 1.0 / 2.0 returns 0.0, 1.0.divide(2.0) returns 0.5, and "1.0" / 2.0 returns 0.5?


Solution

  • If you write divide explicitly, it will work the same way as it does in Java:

    val a = BigDecimal(1.0)
    val b = BigDecimal(2.0)
    val x = a.divide(b) // 0.5
    

    When you use the / operator, that translates to the BigDecimal.div extension from the standard library, which does the following:

    Enables the use of the / operator for BigDecimal instances.

    The scale of the result is the same as the scale of this (divident), and for rounding the RoundingMode.HALF_EVEN rounding mode is used.

    You can take a look at how the different RoundingMode constants work here.