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(除数)で割った後の余りです。この場合は3です。
同じ理由でゼロによる除算ができないため、右側の引数がゼロの場合、モジュロ演算子を使用することはできません。
右側のオペランドとしてゼロを使用しようとすると、除算とモジュロ演算の両方で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. 結論
モジュロ演算子は、他の方法では失われる整数除算の剰余を計算するために使用されます。
特定の数値が偶数か奇数かを判断するなどの単純なことや、循環配列の次の書き込み位置を追跡するなどのより複雑なタスクを実行すると便利です。
サンプルコードはGitHub repositoryにあります。