15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

KotlinでBigDecimal

Last updated at Posted at 2018-01-01

kotlin_800x320.png

Kotlin を趣味で触り始めて数日ですが, Java の痒い所が丁寧にサポートされていて感動しています. BigDecimal 演算もその一つです.

業務アプリでは数値演算が必要になる事が多いですが, Double は使えたものではないので BigDecimal 一択です. そしてこの BigDecimal 演算は, 可読性が低いことこの上ありません.

コーディングスタイル比較

基本編

BigDecimalBasicSample.kt
/**
 * BigDecimal coding style : (a + b) / 2
 */
fun main(args: Array<String>) {
    val a = BigDecimal.ONE
    val b = BigDecimal.TEN

    // Java style
    println(a.add(b).divide(BigDecimal.valueOf(2L), RoundingMode.HALF_EVEN))

    // Kotlin basic style
    println((a + b) / 2.toBigDecimal())
}

Javaはひどい有様です.
Kotlinは四則演算の演算子を適用できるため, 非常に見やすくなりました. ただ 2.toBigDecimal() には依然不満が残ります.

応用編

BigDecimalCustomSample.kt

/** custome operator BigDecimal / Long */
operator fun BigDecimal.div(other : Long) : BigDecimal = this / other.toBigDecimal()

/**
 * BigDecimal coding style : (a + b) / 2
 */
fun main(args: Array<String>) {
    val a = BigDecimal.ONE
    val b = BigDecimal.TEN

    // Java style
    println(a.add(b).divide(BigDecimal.valueOf(2L), RoundingMode.UP))

    // Kotlin custom oeprator style
    println((a + b) / 2)
}

BigDecimal / Long の独自演算子を実装することで, 可読性がより上がりました.

仕組みについて

Kotlin の演算子の実現方法

Kotlin において演算子は, 決められたメソッドを呼び出すことと等価になります. Operator overloading において, 各演算子とそれに対応するメソッドが示されています. 四則演算子を抜粋すると以下になります.

Expression Translated to
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b), a.mod(b) (deprecated)
a..b a.rangeTo(b)

plusなどのメソッドを operator fun で実装することによって, 任意のクラス間の演算子を独自定義することができます.

BigDecimal に対する演算子の実装

kotlin-stdlib に含まれている BigDecimals.kt に演算子の実装が記述されています. サンプルとして除算 "/" の実装を抜粋します. BigDecimal#divide が利用されており, 更に引数に RoundingMode.HALF_EVEN が使われていることが確認できます.

BigDecimals.kt
/**
 * Enables the use of the `/` operator for [BigDecimal] instances.
 *
 * 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.
 */
@kotlin.internal.InlineOnly
public inline operator fun BigDecimal.div(other: BigDecimal): BigDecimal = this.divide(other, RoundingMode.HALF_EVEN)
15
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?