Kotlin BigDecimal 乘法错误结果
Kotlin BigDecimal multiplication wrong results
我需要使用 BigDecimal 进行一些计算,但我对这种行为感到有点惊讶:
val thousand = BigDecimal(1000)
val fee = BigDecimal(0.005)
println(thousand * fee)
您希望控制台包含 5
但结果是 5.000000000000000104083408558608425664715468883514404296875000
我知道我可以限制精度并使用 setScale
进行一些舍入,但真正的问题是为什么首先需要这样做。这个结果显然是错误的。
我错过了什么?
问题很可能与 fee
BigDecimal 的构造有关。这是采用 double
值并将其转换为 BigDecimal
。不幸的是,一些相当简单的小数不可能精确地表示为 double
s 或 float
s,而这个 BigDecimal
的构造函数将把那个不精确的 double
作为它的值。
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.
解决这个问题的方法是使用 String 构造函数,它解决了必须“通过”a double
.
转换的问题
我需要使用 BigDecimal 进行一些计算,但我对这种行为感到有点惊讶:
val thousand = BigDecimal(1000)
val fee = BigDecimal(0.005)
println(thousand * fee)
您希望控制台包含 5
但结果是 5.000000000000000104083408558608425664715468883514404296875000
我知道我可以限制精度并使用 setScale
进行一些舍入,但真正的问题是为什么首先需要这样做。这个结果显然是错误的。
我错过了什么?
问题很可能与 fee
BigDecimal 的构造有关。这是采用 double
值并将其转换为 BigDecimal
。不幸的是,一些相当简单的小数不可能精确地表示为 double
s 或 float
s,而这个 BigDecimal
的构造函数将把那个不精确的 double
作为它的值。
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.
解决这个问题的方法是使用 String 构造函数,它解决了必须“通过”a double
.