BigDecimal の丸めが結局よく分からない時のチートシート

# 問題

適当な実装って入力値を制限していないのに、負数を与えると正しくない結果を返してきたりしますよね。

全くもう...

# 実行結果を見て判断する?

色々検証するのも面倒といえば面倒なので実行してしまえ、というのはある。

必要な際には最新の動作を把握しておきたいので、チートシート代わりのコードが有ると便利よね。


```kotlin
import java.math.BigDecimal
import java.math.RoundingMode

fun main() {
        listOf(
            BigDecimal.valueOf(0.123_456_789),
            BigDecimal.valueOf(-0.123_456_789),
            BigDecimal.valueOf(123_456_789.123_456_789),
            BigDecimal.valueOf(-123_456_789.123_456_789),
        ).forEach {
            test(it)
        }
}

fun test(value: BigDecimal) {

    println("< value: %021.9f".format(value))

    for (scale in -10..10) {
        test(null, value, RoundingMode.DOWN, scale)
    }
    for (scale in -10..10) {
        test(null, value, RoundingMode.UP, scale)
    }
    for (scale in -10..10) {
        test(null, value, RoundingMode.FLOOR, scale)
    }
    // for (scale in -10..10) {
    //     test(null, value, RoundingMode.DOWN, scale)
    //     test(null, value, RoundingMode.UP, scale)
    //     test(null, value, RoundingMode.FLOOR, scale)
    // }
}

fun test(label: String? = null, value: BigDecimal, roundingMode: RoundingMode, scale: Int) {
    val scaledValue = value.setScale(scale, roundingMode)
    println(
        "%-10s : scale - %4d, result - %021.9f (%s)".format(
            label ?: RoundingMode.entries.find { it == roundingMode }?.name ?: "Unknown",
            scale,
            scaledValue,
            scaledValue,
        )
    )
}
```

Kotlin Playground: Edit, Run, Share Kotlin Code Online
https://pl.kotl.in/d-uKLx5Tk

# 出力 抜粋

とりあえず正の数や整数が渡される前提のコードは困るので、引数に制約設けるならちゃんとそういう処理を実装しようね 🐈

```
< value: 00000000000.123456789
DOWN       : scale -  -10, result - 00000000000.000000000 (0E+10)
DOWN       : scale -   -9, result - 00000000000.000000000 (0E+9)
DOWN       : scale -   -8, result - 00000000000.000000000 (0E+8)
DOWN       : scale -   -7, result - 00000000000.000000000 (0E+7)
DOWN       : scale -   -6, result - 00000000000.000000000 (0E+6)
DOWN       : scale -   -5, result - 00000000000.000000000 (0E+5)
DOWN       : scale -   -4, result - 00000000000.000000000 (0E+4)
DOWN       : scale -   -3, result - 00000000000.000000000 (0E+3)
DOWN       : scale -   -2, result - 00000000000.000000000 (0E+2)
DOWN       : scale -   -1, result - 00000000000.000000000 (0E+1)
DOWN       : scale -    0, result - 00000000000.000000000 (0)
DOWN       : scale -    1, result - 00000000000.100000000 (0.1)
DOWN       : scale -    2, result - 00000000000.120000000 (0.12)
DOWN       : scale -    3, result - 00000000000.123000000 (0.123)
DOWN       : scale -    4, result - 00000000000.123400000 (0.1234)
DOWN       : scale -    5, result - 00000000000.123450000 (0.12345)
DOWN       : scale -    6, result - 00000000000.123456000 (0.123456)
DOWN       : scale -    7, result - 00000000000.123456700 (0.1234567)
DOWN       : scale -    8, result - 00000000000.123456780 (0.12345678)
DOWN       : scale -    9, result - 00000000000.123456789 (0.123456789)
DOWN       : scale -   10, result - 00000000000.123456789 (0.1234567890)
UP         : scale -  -10, result - 10000000000.000000000 (1E+10)
UP         : scale -   -9, result - 01000000000.000000000 (1E+9)
UP         : scale -   -8, result - 00100000000.000000000 (1E+8)
UP         : scale -   -7, result - 00010000000.000000000 (1E+7)
UP         : scale -   -6, result - 00001000000.000000000 (1E+6)
UP         : scale -   -5, result - 00000100000.000000000 (1E+5)
UP         : scale -   -4, result - 00000010000.000000000 (1E+4)
UP         : scale -   -3, result - 00000001000.000000000 (1E+3)
UP         : scale -   -2, result - 00000000100.000000000 (1E+2)
UP         : scale -   -1, result - 00000000010.000000000 (1E+1)
UP         : scale -    0, result - 00000000001.000000000 (1)
UP         : scale -    1, result - 00000000000.200000000 (0.2)
UP         : scale -    2, result - 00000000000.130000000 (0.13)
UP         : scale -    3, result - 00000000000.124000000 (0.124)
UP         : scale -    4, result - 00000000000.123500000 (0.1235)
UP         : scale -    5, result - 00000000000.123460000 (0.12346)
UP         : scale -    6, result - 00000000000.123457000 (0.123457)
UP         : scale -    7, result - 00000000000.123456800 (0.1234568)
UP         : scale -    8, result - 00000000000.123456790 (0.12345679)
UP         : scale -    9, result - 00000000000.123456789 (0.123456789)
UP         : scale -   10, result - 00000000000.123456789 (0.1234567890)
FLOOR      : scale -  -10, result - 00000000000.000000000 (0E+10)
FLOOR      : scale -   -9, result - 00000000000.000000000 (0E+9)
FLOOR      : scale -   -8, result - 00000000000.000000000 (0E+8)
FLOOR      : scale -   -7, result - 00000000000.000000000 (0E+7)
FLOOR      : scale -   -6, result - 00000000000.000000000 (0E+6)
FLOOR      : scale -   -5, result - 00000000000.000000000 (0E+5)
FLOOR      : scale -   -4, result - 00000000000.000000000 (0E+4)
FLOOR      : scale -   -3, result - 00000000000.000000000 (0E+3)
FLOOR      : scale -   -2, result - 00000000000.000000000 (0E+2)
FLOOR      : scale -   -1, result - 00000000000.000000000 (0E+1)
FLOOR      : scale -    0, result - 00000000000.000000000 (0)
FLOOR      : scale -    1, result - 00000000000.100000000 (0.1)
FLOOR      : scale -    2, result - 00000000000.120000000 (0.12)
FLOOR      : scale -    3, result - 00000000000.123000000 (0.123)
FLOOR      : scale -    4, result - 00000000000.123400000 (0.1234)
FLOOR      : scale -    5, result - 00000000000.123450000 (0.12345)
FLOOR      : scale -    6, result - 00000000000.123456000 (0.123456)
FLOOR      : scale -    7, result - 00000000000.123456700 (0.1234567)
FLOOR      : scale -    8, result - 00000000000.123456780 (0.12345678)
FLOOR      : scale -    9, result - 00000000000.123456789 (0.123456789)
FLOOR      : scale -   10, result - 00000000000.123456789 (0.1234567890)
```

```
< value: -0000000000.123456789
DOWN       : scale -  -10, result - 00000000000.000000000 (0E+10)
DOWN       : scale -   -9, result - 00000000000.000000000 (0E+9)
DOWN       : scale -   -8, result - 00000000000.000000000 (0E+8)
DOWN       : scale -   -7, result - 00000000000.000000000 (0E+7)
DOWN       : scale -   -6, result - 00000000000.000000000 (0E+6)
DOWN       : scale -   -5, result - 00000000000.000000000 (0E+5)
DOWN       : scale -   -4, result - 00000000000.000000000 (0E+4)
DOWN       : scale -   -3, result - 00000000000.000000000 (0E+3)
DOWN       : scale -   -2, result - 00000000000.000000000 (0E+2)
DOWN       : scale -   -1, result - 00000000000.000000000 (0E+1)
DOWN       : scale -    0, result - 00000000000.000000000 (0)
DOWN       : scale -    1, result - -0000000000.100000000 (-0.1)
DOWN       : scale -    2, result - -0000000000.120000000 (-0.12)
DOWN       : scale -    3, result - -0000000000.123000000 (-0.123)
DOWN       : scale -    4, result - -0000000000.123400000 (-0.1234)
DOWN       : scale -    5, result - -0000000000.123450000 (-0.12345)
DOWN       : scale -    6, result - -0000000000.123456000 (-0.123456)
DOWN       : scale -    7, result - -0000000000.123456700 (-0.1234567)
DOWN       : scale -    8, result - -0000000000.123456780 (-0.12345678)
DOWN       : scale -    9, result - -0000000000.123456789 (-0.123456789)
DOWN       : scale -   10, result - -0000000000.123456789 (-0.1234567890)
UP         : scale -  -10, result - -10000000000.000000000 (-1E+10)
UP         : scale -   -9, result - -1000000000.000000000 (-1E+9)
UP         : scale -   -8, result - -0100000000.000000000 (-1E+8)
UP         : scale -   -7, result - -0010000000.000000000 (-1E+7)
UP         : scale -   -6, result - -0001000000.000000000 (-1E+6)
UP         : scale -   -5, result - -0000100000.000000000 (-1E+5)
UP         : scale -   -4, result - -0000010000.000000000 (-1E+4)
UP         : scale -   -3, result - -0000001000.000000000 (-1E+3)
UP         : scale -   -2, result - -0000000100.000000000 (-1E+2)
UP         : scale -   -1, result - -0000000010.000000000 (-1E+1)
UP         : scale -    0, result - -0000000001.000000000 (-1)
UP         : scale -    1, result - -0000000000.200000000 (-0.2)
UP         : scale -    2, result - -0000000000.130000000 (-0.13)
UP         : scale -    3, result - -0000000000.124000000 (-0.124)
UP         : scale -    4, result - -0000000000.123500000 (-0.1235)
UP         : scale -    5, result - -0000000000.123460000 (-0.12346)
UP         : scale -    6, result - -0000000000.123457000 (-0.123457)
UP         : scale -    7, result - -0000000000.123456800 (-0.1234568)
UP         : scale -    8, result - -0000000000.123456790 (-0.12345679)
UP         : scale -    9, result - -0000000000.123456789 (-0.123456789)
UP         : scale -   10, result - -0000000000.123456789 (-0.1234567890)
FLOOR      : scale -  -10, result - -10000000000.000000000 (-1E+10)
FLOOR      : scale -   -9, result - -1000000000.000000000 (-1E+9)
FLOOR      : scale -   -8, result - -0100000000.000000000 (-1E+8)
FLOOR      : scale -   -7, result - -0010000000.000000000 (-1E+7)
FLOOR      : scale -   -6, result - -0001000000.000000000 (-1E+6)
FLOOR      : scale -   -5, result - -0000100000.000000000 (-1E+5)
FLOOR      : scale -   -4, result - -0000010000.000000000 (-1E+4)
FLOOR      : scale -   -3, result - -0000001000.000000000 (-1E+3)
FLOOR      : scale -   -2, result - -0000000100.000000000 (-1E+2)
FLOOR      : scale -   -1, result - -0000000010.000000000 (-1E+1)
FLOOR      : scale -    0, result - -0000000001.000000000 (-1)
FLOOR      : scale -    1, result - -0000000000.200000000 (-0.2)
FLOOR      : scale -    2, result - -0000000000.130000000 (-0.13)
FLOOR      : scale -    3, result - -0000000000.124000000 (-0.124)
FLOOR      : scale -    4, result - -0000000000.123500000 (-0.1235)
FLOOR      : scale -    5, result - -0000000000.123460000 (-0.12346)
FLOOR      : scale -    6, result - -0000000000.123457000 (-0.123457)
FLOOR      : scale -    7, result - -0000000000.123456800 (-0.1234568)
FLOOR      : scale -    8, result - -0000000000.123456790 (-0.12345679)
FLOOR      : scale -    9, result - -0000000000.123456789 (-0.123456789)
FLOOR      : scale -   10, result - -0000000000.123456789 (-0.1234567890)
```


# 参考

RoundingMode (Java Platform SE 8 )
https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html

Oracle Help Center - Search
https://docs.oracle.com/search/?q=BigDecimal&pg=1&size=10&showfirstpage=true&lang=en