Javaにおけるモジュロ演算子
1.概要
この短いチュートリアルでは、モジュロ演算子とは何か、そしていくつかの一般的なユースケースでそれをJavaでどのように使用できるかを説明します。
2.モジュロ演算子
Javaの単純分割の欠点から始めましょう。
-
除算演算子の両側のオペランドの型が
int
の場合、演算結果は別の__intになります。
@Test
public void whenIntegerDivision__thenLosesRemainder() {
assertThat(11/4).isEqualTo(2);
}
少なくとも1つのオペランドの型が
float
または__doubleの場合、同じ除算で異なる結果になります。
@Test
public void whenDoubleDivision__thenKeepsRemainder() {
assertThat(11/4.0).isEqualTo(2.75);
}
整数を除算すると、除算演算の残りが失われることがわかります。
モジュロ演算子は、正確にこの余りを与えます。
@Test
public void whenModulo__thenReturnsRemainder() {
assertThat(11 % 4).isEqualTo(3);
}
-
残りは、11(配当)を4(約数)で割った後に残っているものです。
同じ理由で、ゼロによる除算は不可能であるため、右側の引数がゼロのときはモジュロ演算子を使用することはできません。
右側のオペランドとしてゼロを使おうとすると、除算とモジュロ演算の両方が
ArithmeticException
をスローします。
@Test(expected = ArithmeticException.class)
public void whenDivisionByZero__thenArithmeticException() {
double result = 1/0;
}
@Test(expected = ArithmeticException.class)
public void whenModuloByZero__thenArithmeticException() {
double result = 1 % 0;
}
3.一般的なユースケース
モジュロ演算子の最も一般的な使用例は、与えられた数が奇数か偶数かを調べることです。
任意の数と2の間のモジュロ演算の結果が1に等しい場合、それは奇数です。
@Test
public void whenDivisorIsOddAndModulusIs2__thenResultIs1() {
assertThat(3 % 2).isEqualTo(1);
}
一方、結果がゼロの場合(つまり余りがない場合)、偶数になります。
@Test
public void whenDivisorIsEvenAndModulusIs2__thenResultIs0() {
assertThat(4 % 2).isEqualTo(0);
}
モジュロ演算のもう1つの良い使い方は、円形配列内の次の空きスポットのインデックスを追跡することです。
int
値の循環キューの単純な実装では、要素は固定サイズの配列に保持されます。
要素を循環キューにプッシュしたいときはいつでも、すでに挿入したアイテム数に1を加えた値とキュー容量のモジュロを計算することによって、次の空き位置を計算するだけです。
@Test
public void whenItemsIsAddedToCircularQueue__thenNoArrayIndexOutOfBounds() {
int QUEUE__CAPACITY= 10;
int[]circularQueue = new int[QUEUE__CAPACITY];
int itemsInserted = 0;
for (int value = 0; value < 1000; value++) {
int writeIndex = ++itemsInserted % QUEUE__CAPACITY;
circularQueue[writeIndex]= value;
}
}
モジュロ演算子を使用して、
writeIndex
が配列の境界から外れないようにします。したがって、
ArrayIndexOutOfBoundsException
が発生することはありません。
ただし、
QUEUE
CAPACITY__個以上のアイテムを挿入すると、次のアイテムによって最初のアイテムが上書きされます。
4.まとめ
モジュロ演算子を使用して、そうでなければ失われた整数除算の剰余を計算します。
与えられた数が偶数か奇数かを判断するなどの単純なことや、円形配列内の次の書き込み位置を追跡することなどのより複雑な作業を行うのに便利です。
サンプルコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-lang-syntax[GitHub repository]にあります。