記録

主にAndroidアプリ開発に関する知見やその周辺に関わることについて記事をかいています

Kotlinで数値を単位付きの数字にする

仕事で開発をしていて、数値を次の要件のように単位表示することになった

要件

  • 1万未満はそのままの数値を表示(例:7,777)
  • 1万以上は単位をつけた数字として表示(例:770,000→77万)
  • 単位表示時に1桁の場合は小数点第1位まで表示(例:77,000→7.7万)
  • 4桁の場合は3桁のカンマ区切りを行う(例:77,770,000→7,777万)

技術的な要件

  • 複数の画面で利用したいのでLongの拡張関数にする
  • 単位文字は Context.getString(stringRes) で取得できる

実装

まずは単位をつけた場合の数値を文字列として返すようにする

fun Long.toUnits(): String {
    var num = this
    while ("$num".length > 4) {
        num /= 10000
    }
    return "%,d".format(num)
}

fun main() {
    println(7777L.toUnits()) // 7,777
    println(770000L.toUnits()) // 77
    println(77000L.toUnits()) // 7
    println(77770000L.toUnits()) // 7,777
}

これに単位表示1桁の場合の小数点第1位表示をつける

fun Long.toUnits(): String {
    var num = this
    var rem = 0L
    while ("$num".length > 4) {
        rem = num % 10000
        num /= 10000
    }

    val numString = if ("$num".length == 1) 
        "${num}.${rem / 1000}" else 
        "%,d".format(num)

    return numString
}

fun main() {
    println(7777L.toUnits()) // 7,777
    println(770000L.toUnits()) // 77
    println(77000L.toUnits()) // 7.7
    println(77770000L.toUnits()) // 7,777
}

次に単位をつけるようにしてみる

fun Long.toUnits(): String {
    val units = arrayOf("万", "億")
    var num = this
    var rem = 0L
    var index = -1
    while ("$num".length > 4 && index < units.lastIndex) {
        rem = num % 10000
        num /= 10000
        index += 1
    }
    
    val unit = if (index > -1) units[index] else ""
    val numString = if ("$num".length == 1) 
        "${num}.${rem / 1000}" else 
        "%,d".format(num)

    return numString + unit
}

fun main() {
    println(7777L.toUnits()) // 7,777
    println(770000L.toUnits()) // 77万
    println(77000L.toUnits()) // 7.7万
    println(77770000L.toUnits()) // 7,777万
    println(770000000L.toUnits()) // 7.7億
    println(7777770000000L.toUnits()) // 77,777億
}

だいたい完成したようなものなので、あとは単位文字を外部から受け取るようにする

fun Long.toUnits(units: Array<String>): String {
    ...
}

fun main() {
    val units = arrayOf("万", "億")
    println(7777L.toUnits(units)) // 7,777
    println(770000L.toUnits(units)) // 77万
    println(77000L.toUnits(units)) // 7.7万
    println(77770000L.toUnits(units)) // 7,777万
    println(770000000L.toUnits(units)) // 7.7億
    println(7777770000000L.toUnits(units)) // 77,777億
}

最終版