Skip to content
[Scala] scalaのBigDecimalをjava.text.DecimalFormatで変換するとずれることがある
java-tips-scala-tips
2019-11-07

なんかまだ合点がいってないのだが、細かい桁計算が必要でscalaのBigDecimalを使っていて、それを文字列で打ち出す必要が出た際に、javaのDecimalFormatを使ったら出力文字列が合致しなかった。

val a = "4.95"
val b = "0.000000000000000001"

val bigA = BigDecimal(a)
val bigB = BigDecimal(b)

val bigC = bigA+bigB

bigC.toString() // シンプルにtoStringにしたほうが正しい文字列になった

val fm = new java.text.DecimalFormat("0.###################")

println(fm.format(bigA))
println(fm.format(bigB))
println(fm.format(bigC)) // bigA+bigB に文字列一致しない

val fm2 = new java.text.DecimalFormat("0.0000000000000000000")

println(fm2.format(bigA))
println(fm2.format(bigB))
println(fm2.format(bigC)) // bigA+bigB に文字列一致しない
val a = "4.95"
val b = "0.000000000000000001"

val bigA = BigDecimal(a)
val bigB = BigDecimal(b)

val bigC = bigA+bigB

bigC.toString() // シンプルにtoStringにしたほうが正しい文字列になった

val fm = new java.text.DecimalFormat("0.###################")

println(fm.format(bigA))
println(fm.format(bigB))
println(fm.format(bigC)) // bigA+bigB に文字列一致しない

val fm2 = new java.text.DecimalFormat("0.0000000000000000000")

println(fm2.format(bigA))
println(fm2.format(bigB))
println(fm2.format(bigC)) // bigA+bigB に文字列一致しない

REPL出力

a: String = 4.95
b: String = 0.000000000000000001

biga: scala.math.BigDecimal = 4.95
bigb: scala.math.BigDecimal = 1E-18

bigc: scala.math.BigDecimal = 4.950000000000000001

res0: String = 4.950000000000000001
// シンプルにtoStringにしたほうが正しい文字列になった

fm: java.text.DecimalFormat = java.text.DecimalFormat@674dc

4.95
0.000000000000000001
4.95  // bigA+bigB に文字列一致しない

fm2: java.text.DecimalFormat = java.text.DecimalFormat@674dc

4.9500000000000000000
0.0000000000000000010
4.9500000000000000000  // bigA+bigB に文字列一致しない
a: String = 4.95
b: String = 0.000000000000000001

biga: scala.math.BigDecimal = 4.95
bigb: scala.math.BigDecimal = 1E-18

bigc: scala.math.BigDecimal = 4.950000000000000001

res0: String = 4.950000000000000001
// シンプルにtoStringにしたほうが正しい文字列になった

fm: java.text.DecimalFormat = java.text.DecimalFormat@674dc

4.95
0.000000000000000001
4.95  // bigA+bigB に文字列一致しない

fm2: java.text.DecimalFormat = java.text.DecimalFormat@674dc

4.9500000000000000000
0.0000000000000000010
4.9500000000000000000  // bigA+bigB に文字列一致しない

ネットで調べて scalaのBigDecimalとjavaのBigDecimalがちょっと違うよ(MathContext._UNLIMITED_設定関係)って話は出てきたが、DecimalFormatが違うって話はよくわからんかった。