Operator modulo w Javie

1. Przegląd

W tym krótkim samouczku pokażemy, czym jest operator modulo i jak możemy go używać z Javą w niektórych typowych przypadkach użycia.

2. Operator modulo

Zacznijmy od niedociągnięć prostego podziału w Javie.

Jeśli operandy po obu stronach operatora dzielenia mają typ int , wynikiem operacji jest inna int:

@Test public void whenIntegerDivision_thenLosesRemainder() { assertThat(11 / 4).isEqualTo(2); }

Ten sam podział daje nam inny wynik, gdy co najmniej jeden z operandów ma typ float lub double:

@Test public void whenDoubleDivision_thenKeepsRemainder() { assertThat(11 / 4.0).isEqualTo(2.75); }

Możemy zauważyć, że podczas dzielenia liczb całkowitych tracimy resztę operacji dzielenia.

Operator modulo daje nam dokładnie tę resztę:

@Test public void whenModulo_thenReturnsRemainder() { assertThat(11 % 4).isEqualTo(3); }

Reszta to to, co pozostaje po podzieleniu 11 (dywidenda) przez 4 (dzielnik) - w tym przypadku 3.

Z tego samego powodu dzielenie przez zero nie jest możliwe, nie można użyć operatora modulo, gdy argument po prawej stronie ma wartość zero.

Zarówno dzielenie, jak i operacja modulo generują wyjątek ArithmeticException, gdy próbujemy użyć zera jako operandu po prawej stronie:

@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. Przypadki wspólnego użytkowania

Najczęstszym przypadkiem użycia operatora modulo jest sprawdzenie, czy dana liczba jest nieparzysta czy parzysta.

Jeśli wynik operacji modulo między dowolną liczbą a dwoma jest równy jeden, jest to liczba nieparzysta:

@Test public void whenDivisorIsOddAndModulusIs2_thenResultIs1() { assertThat(3 % 2).isEqualTo(1); }

Z drugiej strony, jeśli wynik wynosi zero (tj. Nie ma reszty), jest to liczba parzysta:

@Test public void whenDivisorIsEvenAndModulusIs2_thenResultIs0() { assertThat(4 % 2).isEqualTo(0); }

Innym dobrym zastosowaniem operacji modulo jest śledzenie indeksu następnego wolnego miejsca w tablicy kołowej.

W prostej implementacji kolejki cyklicznej dla wartości int elementy są przechowywane w tablicy o stałym rozmiarze.

Za każdym razem, gdy chcemy umieścić element w naszej kolejce cyklicznej, po prostu obliczamy następną wolną pozycję, obliczając modulo liczby elementów, które już wstawiliśmy, plus 1 i pojemność kolejki:

@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; } }

Używając operatora modulo, zapobiegamy wypadnięciu writeIndex poza granice tablicy, dlatego nigdy nie otrzymamy wyjątku ArrayIndexOutOfBoundsException .

Jednak gdy wstawimy więcej elementów niż QUEUE_CAPACITY , następny element zastąpi pierwszy.

4. Wniosek

Operator modulo służy do obliczania pozostałej części dzielenia liczb całkowitych, która w przeciwnym razie została utracona.

Przydaje się do wykonywania prostych rzeczy, takich jak ustalenie, czy dana liczba jest parzysta czy nieparzysta, a także bardziej złożonych zadań, takich jak śledzenie następnej pozycji zapisu w tablicy kołowej.

Przykładowy kod jest dostępny w repozytorium GitHub.