Hi, I think “/” implementation in stdlib can create very subtle bugs, like this:
val v1 = BigDecimal( “0.007”) / BigDecimal( “2”)
val v2 = BigDecimal( “0.007”).divide(BigDecimal( “2”))
println(“v1=$v1 v2=$v2”)
Produces this:
v1=0.004 v2=0.0035
Hi, I think “/” implementation in stdlib can create very subtle bugs, like this:
val v1 = BigDecimal( “0.007”) / BigDecimal( “2”)
val v2 = BigDecimal( “0.007”).divide(BigDecimal( “2”))
println(“v1=$v1 v2=$v2”)
Produces this:
v1=0.004 v2=0.0035
It seems like rounding is mode is passed when using operator call and a final result depends on scaling and precision:
// expected: 0.25
println("1/4 = ${1.toBigDecimal() / 4.BigDecimal()}") // prints: 0
println("1.0/4 = ${BigDecimal("1.0") / 4.toBigDecimal()}") // prints: 0.2
println("1.00/4 = ${BigDecimal("1.00") / 4.toBigDecimal()}") // prints: 0.25
From the documentation of the operator div
extension:
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.
The documentation for the divide(BigDecimal divisor)
method, however, states the following:
Returns a
BigDecimal
whose value is(this / divisor)
, and whose preferred scale is(this.scale() - divisor.scale())
; if the exact quotient cannot be represented (because it has a non-terminating decimal expansion) anArithmeticException
is thrown.
The key point here is that the latter only mentions the preferred scale. The documentation has the following to say about preferred scales:
These (the preferred, ed.) scales are the ones used by the methods which return exact arithmetic results; except that an exact divide may have to use a larger scale since the exact result may have more digits. For example,
1/32
is0.03125
.