3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ZOZOAdvent Calendar 2024

Day 13

Kotlinでの`roundTo〇〇`を用いた四捨五入は負の数に気をつけて!

Posted at

はじめに

Kotlinでは数値を四捨五入する場合、roundToIntroundToLongを使用します。ただし、負の値を四捨五入する際には1点注意が必要です。この記事では、KotlinのroundToIntを用いてどのような挙動になるのかを詳しく解説します。

まず結論

いきなり結論からの共有です。roundTo〇〇は負の数(-X.5)に対して以下の結果になってしまう可能性があります。

a. (-7.5).roundToInt()とコーディングの場合
値がマイナスの記号を含めてそのまま評価され、-7.5を一番近い切り上げられた整数(-7)を返します

b. -7.5.roundToInt()とコーディングの場合
マイナスの記号は一旦考慮されず7.5を評価し、四捨五入して8とした後、マイナス記号が後から適用され、結果として-8を返します

c. val num = -7.5 と変数に格納して、変数に対してroundToInt()を呼び出した場合
こちらもaのケースと同様に、値がマイナスの記号を含めてそのまま評価されるため整数(-7)を返します

KotlinでのroundTo〇〇

まずここではKotlinのroundToIntのソースコードがなっているかを覗いてみましょう!

public actual fun Double.roundToInt(): Int = when {
    isNaN() -> throw IllegalArgumentException("Cannot round NaN value.")
    this > Int.MAX_VALUE -> Int.MAX_VALUE
    this < Int.MIN_VALUE -> Int.MIN_VALUE
    else -> nativeMath.round(this).toInt()// Int範囲内の数値であればここに入る
}

KotlinのInt範囲内に収まっているDoubleで数字であれば、thisで自身の値を更に次のround関数に引数として渡し、Int型に変換して返しているのが分かります。また、round関数内ではビットワイズのシフト演算を使用して四捨五入の計算が行われていました。

検証してみよう

それは実際にこの関数を使用して、期待する四捨五入の結果を得られるのかを検証してみましょう。

➕正数に対しての四捨五入

    val case1 = 3.14.roundToInt()// 3
    val case2 = 5.7.roundToInt()// 6
    val case3 = 8.5.roundToInt()// 9

上記コードのように、小数点部分が0.5以上であれば値の切り上げ、0.5より小さい場合は切り下げがされているのを確認できると思います。

では続けてそれぞれをマイナス値にした場合はどうなるのか確認してみましょう。

➖負数に対しての四捨五入

    val case1 = -3.14.roundToInt()// -3
    val case2 = -5.7.roundToInt()// -6
    val case3 = -8.5.roundToInt()// -9

正数の結果にそのままマイナスが付くような結果になりましたね。ではそれぞれに括弧をつけるとどうなるでしょう?

    val case1 = (-3.14).roundToInt()// -3
    val case2 = (-5.7).roundToInt()// -6
    val case3 = (-8.5).roundToInt()// -8

case1とcase2は同じ結果ですが、case3は-9ではなく-8になっているのが確認できます。
上記は変数に値を格納した場合でも同じ結果になります。

    val num = -8.5
    val case1 = num.roundToInt()// -8

なぜこのような挙動になるのか?

ここでは括弧ありと無しで、値の評価にどんな違いがあるのかを説明します。
下記例になります。

a. (-8.5).roundToInt()

  • 丸括弧を用いることで、-8.5全体が計算の対象になります
  • 小数点が0.5であるため-8.5より大きい整数である-8に切り上げとなります
  • 結果、-8.5-8に丸められます

b. -8.5.roundToInt()

  • この場合、まず8.5の絶対値部分に対してroundToIntが実行されます
    • 8.59に丸められる
  • roundの処理によって返却された値の先頭に-が適用され、結果は-9になります

実際のコード例

以下のコードで実際の挙動を確認できます:

fun main() {
    val case1 = (-7.5).roundToInt()
    val case2 = -7.5.roundToInt()

    println("(-7.5).roundToInt() の結果: $case1") // 結果: -7
    println("-7.5.roundToInt() の結果: $case2")  // 結果: -8
}

Kotlin Playgroundのコード

参考資料

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?