java.math.BigDecimal除法不准确

时间:2018-08-07 04:43:53

标签: java kotlin bigdecimal

在Kotlin中,BigDecimal部门返回奇怪的结果。

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

但是:

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

那为什么会发生这种情况?如何使1.0 / 2.0在不使用divide()给出scale参数的情况下使用BigDecimal返回0.5?

更新:

以下是完整的代码:

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

更新2:

根据@ user2864740

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

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

所以结果令人困惑。对于BigDecimal,为什么1.0 / 2.0返回0.0,1.0.divide(2.0)返回0.5,而"1.0" / 2.0返回0.5?

2 个答案:

答案 0 :(得分:5)

如果您显式地编写divide,它将与Java中的工作方式相同:

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

使用/运算符时,它将转换为标准库中的BigDecimal.div扩展名,该扩展名将执行以下操作:

  

为BigDecimal实例启用/运算符。

     

结果的小数位数与该(小数)的小数位数相同,并且用于舍入RoundingMode。使用HALF_EVEN舍入模式。

您可以看看不同的RoundingMode常量here的工作原理。

答案 1 :(得分:1)

1.1double文字

  

如果浮点文字以字母F或f结尾,则其类型为float;否则,其类型为double,并且可以选择以字母D或d结尾。

     

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

因此,在将值传递到BigDecimal时,由于double值,您已经失去了精度。 BigDecimal(1.1)等同于double d = 1.1; BigDecimal(d)。您需要将值作为字符串传递

BigDecimal("1.1")

除非该值可精确表示为1.5之类的双精度值