Der Modulo Operator in Java

Der Modulo-Operator in Java

1. Überblick

In diesem kurzen Tutorial zeigen wir, was der Modulo-Operator ist und wie wir ihn mit Java für einige gängige Anwendungsfälle verwenden können.

2. Der Modulo-Operator

Beginnen wir mit den Mängeln der einfachen Teilung in Java.

Wenn die Operanden auf beiden Seiten des Divisionsoperators den Typint haben, ist das Ergebnis der Operation ein weiteresint:

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

Dieselbe Division ergibt ein anderes Ergebnis, wenn mindestens einer der Operanden den Typfloat oderdouble: hat

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

Wir können beobachten, dass wir den Rest einer Divisionsoperation verlieren, wenn wir ganze Zahlen dividieren.

Der Modulo-Operator gibt uns genau diesen Rest:

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

Der Rest bleibt nach Division von 11 (Dividende) durch 4 (Divisor) - in diesem Fall 3.

Aus dem gleichen Grund ist eine Division durch Null nicht möglich. Es ist nicht möglich, den Modulo-Operator zu verwenden, wenn das Argument auf der rechten Seite Null ist.

Sowohl die Division als auch die Modulo-Operation werfen einArithmeticException, wenn wir versuchen, Null als Operanden auf der rechten Seite zu verwenden:

@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. Häufige Anwendungsfälle

Der häufigste Anwendungsfall für den Modulo-Operator besteht darin, herauszufinden, ob eine bestimmte Zahl ungerade oder gerade ist.

Wenn das Ergebnis der Modulo-Operation zwischen einer beliebigen Zahl und zwei gleich eins ist, ist es eine ungerade Zahl:

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

Wenn andererseits das Ergebnis Null ist (d. H. es gibt keinen Rest), es ist eine gerade Zahl:

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

Eine weitere gute Verwendung der Modulo-Operation besteht darin, den Index des nächsten freien Punkts in einer kreisförmigen Anordnung zu verfolgen.

Bei einer einfachen Implementierung einer kreisförmigen Warteschlange fürint-Werte werden die Elemente in einem Array fester Größe gehalten.

Jedes Mal, wenn wir ein Element in unsere Warteschlange verschieben möchten, berechnen wir einfach die nächste freie Position, indem wir das Modulo aus der Anzahl der bereits eingefügten Elemente plus 1 und der Kapazität der Warteschlange berechnen:

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

Mit dem Modulo-Operator verhindern wir, dasswriteIndex aus den Grenzen des Arrays herausfallen. Daher erhalten wir niemalsArrayIndexOutOfBoundsException.

Sobald wir jedoch mehr alsQUEUE_CAPACITYElemente einfügen, überschreibt das nächste Element das erste.

4. Fazit

Der Modulo-Operator wird verwendet, um den Rest einer Ganzzahldivision zu berechnen, die ansonsten verloren gegangen ist.

Es ist nützlich, einfache Dinge zu tun, wie herauszufinden, ob eine bestimmte Zahl gerade oder ungerade ist, sowie komplexere Aufgaben wie das Verfolgen der nächsten Schreibposition in einem kreisförmigen Array.

Der Beispielcode ist inGitHub repository verfügbar.