Was ist die Syntax für Mod in Java

231

Als Beispiel im Pseudocode:

if ((a mod 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}
Bob
quelle

Antworten:

357

Anstelle des Modulo - Operator, der etwas andere Semantik hat, für nicht-negative ganze Zahlen sind , können Sie die Verwendung Rest Operator %. Für Ihr genaues Beispiel:

if ((a % 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}

Dies kann zu einem Einzeiler vereinfacht werden:

isEven = (a % 2) == 0;
Cody Hatch
quelle
80
Das wenn / sonst ist unnötig, benutze einfach isEven = (a% 2) == 0,
Steve Kuo
59
Vorsicht mit den Begriffen mod und modular, da n (mod m) IMMER> = 0 ist, aber nicht n% m. n% m liegt im Bereich> -m und <m. Obwohl Java einen Restoperator für int- und long-Typen hat, hat es keine Modulfunktion oder keinen Operator. Dh -12% 10 = -2, während -12 mod 10 = 8. Wenn der Operator% einen negativen Wert für n% m zurückgibt, erhalten Sie mit (n% m) + m n mod m. BigInteger bietet Funktionen für beide und die Spezifikationen für sie erklären den Unterschied recht gut. Auch vorsichtig mit Null. In der Mathematik ist Null zwar eine gerade Zahl, aber NICHT positiv oder negativ.
Jim
4
@ nl-x Wahrscheinlich, weil es besser ist, explizit Vorrang zu haben, als es der Konvention zu überlassen. Ich jedenfalls wusste nicht, dass dies %vorher ausgewertet wurde, bevor ==ich es nachgeschlagen habe, daher wäre unklar, ob der Ausdruck äquivalent zu (a%2)==0oder ist a%(2==0). Ich denke, es ist weniger wichtig in Java, wo ein Boolescher Wert nicht mit einer ganzen Zahl identisch ist
Matthew Sainsbury
8
Dies ist nicht der Moduloperator, sondern der Restoperator. Bitte korrigieren Sie den Beitrag!
Kieren Johnstone
2
Boolescher gerader Wert = ((a & 1) == 0). Viel einfacher.
Mdev
111

Hier ist die Darstellung Ihres Pseudocodes in minimalem Java-Code.

boolean isEven = a % 2 == 0;

Ich werde es jetzt in seine Komponenten zerlegen. Der Moduloperator in Java ist das Prozentzeichen (%). Daher gibt ein int% int ein anderes int zurück. Der Operator double equals (==) wird zum Vergleichen von Werten verwendet, z. B. eines Int-Paares, und gibt einen Booleschen Wert zurück. Dies wird dann der booleschen Variablen 'isEven' zugewiesen. Basierend auf der Priorität des Operators wird der Modul vor dem Vergleich bewertet.

Martinatime
quelle
12
minimal wäre ohne die Klammern;)
Pstanton
3
Es ist ein Restoperator, kein Moduloperator.
Marquis von Lorne
@ user207421 Sein Name ist in der Tat Restoperator aber sind sie nicht gleichwertig: „ Modul - 4. (Berechnung, Programmierung) Ein Operator zwischen zwei Zahlen gesetzt, um den Rest der Teilung dieser Zahlen zu bekommen.“?
GeroldBroser setzt Monica
93

Da alle anderen bereits die Antwort gegeben haben, werde ich einen zusätzlichen Kontext hinzufügen. % Der Operator "Modul" führt tatsächlich die Restoperation aus. Der Unterschied zwischen Mod und Rem ist subtil, aber wichtig.

(-1 mod 2) würde normalerweise 1 ergeben. Insbesondere bei zwei ganzen Zahlen, X und Y, gibt die Operation (X mod Y) tendenziell einen Wert im Bereich [0, Y] zurück. Anders gesagt, der Modul von X und Y ist immer größer oder gleich Null und kleiner als Y.

Wenn Sie dieselbe Operation mit dem Operator "%" oder rem ausführen, wird das Vorzeichen des X-Werts beibehalten. Wenn X negativ ist, erhalten Sie ein Ergebnis im Bereich (-Y, 0]. Wenn X positiv ist, erhalten Sie ein Ergebnis im Bereich [0, Y).

Oft spielt diese subtile Unterscheidung keine Rolle. Zurück zu Ihrer Code-Frage: Es gibt jedoch mehrere Möglichkeiten, nach "Gleichmäßigkeit" zu suchen.

Der erste Ansatz ist gut für Anfänger, weil er besonders ausführlich ist.

// Option 1: Clearest way for beginners
boolean isEven;
if ((a % 2) == 0)
{
  isEven = true
}
else
{
  isEven = false
}

Der zweite Ansatz nutzt die Sprache besser aus und führt zu einem prägnanteren Code. (Vergessen Sie nicht, dass der Operator == einen Booleschen Wert zurückgibt.)

// Option 2: Clear, succinct, code
boolean isEven = ((a % 2) == 0);

Der dritte Ansatz dient der Vollständigkeit und verwendet den ternären Operator. Obwohl der ternäre Operator oft sehr nützlich ist, halte ich in diesem Fall den zweiten Ansatz für überlegen.

// Option 3: Ternary operator
boolean isEven = ((a % 2) == 0) ? true : false;

Der vierte und letzte Ansatz besteht darin, das Wissen über die binäre Darstellung von ganzen Zahlen zu nutzen . Wenn das niedrigstwertige Bit 0 ist, ist die Zahl gerade. Dies kann mit dem bitweisen Operator (&) überprüft werden . Während dieser Ansatz der schnellste ist (Sie führen eine einfache Bitmaskierung anstelle einer Division durch), ist er für Anfänger möglicherweise etwas fortgeschritten / kompliziert.

// Option 4: Bitwise-and
boolean isEven = ((a & 1) == 0);

Hier habe ich den bitweisen Operator und verwendet und ihn in der in Option 2 gezeigten prägnanten Form dargestellt. Das Umschreiben in Form von Option 1 (und alternativ in Option 3) bleibt dem Leser als Übung überlassen. ;)

Hoffentlich hilft das.

Rob Rolnick
quelle
Danke Rob. Diese Verwirrung verursacht enorme Schwierigkeiten, Programmierern zu erklären, wie Algorithmen mit mathematischen Eigenschaften aus der modularen Arithmetik implementiert werden. Der Rest ist KEIN Modul, aber man kann schnell einen Modul aus den Resten ableiten.
Jim
1
@TickledPink Außer, dass dies nicht in Java kompiliert wird.
Eugene Beresovsky
33

Mit dieser Methode können Sie die% (REM) -Operation von Java wie MOD für negative X- und positive Y-Werte verwenden:

private int mod(int x, int y)
{
    int result = x % y;
    if (result < 0)
    {
        result += y;
    }
    return result;
}

oder mit dem ternären Operator (kürzer, aber in einigen Situationen nicht möglich oder weniger effizient):

private int mod(int x, int y)
{
    int result = x % y;
    return result < 0? result + y : result;
}
Zom-B
quelle
12

Java hat eigentlich keinen Modulo-Operator wie C. % in Java ist ein Restoperator. Bei positiven Ganzzahlen funktioniert es genau wie Modulo, bei negativen Ganzzahlen jedoch anders und im Gegensatz zu Modulo auch bei Gleitkommazahlen. Trotzdem ist es selten,% für etwas anderes als positive ganze Zahlen zu verwenden. Wenn Sie es also als Modulo bezeichnen möchten, fühlen Sie sich frei!

Greg Charles
quelle
Aber ich möchte einen echten Modulo-Operator, der auch für negative Ganzzahlen funktioniert, sodass array[x mod array.length]immer auf ein Element in meinem Array zugegriffen wird, anstatt zu versuchen, negative Positionen zu indizieren.
Kris
2
(x % y + y) % y oder ab Java 8,Math.floorMod(x, y)
Greg Charles
12

Während es möglich ist, ein korrektes Modulo zu erstellen, indem überprüft wird, ob der Wert negativ ist, und wenn dies der Fall ist (wie von vielen vorgeschlagen), gibt es eine kompaktere Lösung.

(a % b + b) % b

Dies führt zuerst das Modulo aus, begrenzt den Wert auf den Bereich -b -> + b und addiert dann b, um sicherzustellen, dass der Wert positiv ist, und lässt das nächste Modulo ihn auf den Bereich 0 -> b begrenzen.

Hinweis: Wenn b negativ ist, ist das Ergebnis ebenfalls negativ

Stefan T.
quelle
Dies kann überlaufen, wenn a und b beide große Zahlen sind, daher ist es keine korrekte Lösung.
Trixie Wolf
11

Der Code läuft viel schneller ohne Modulo:

public boolean isEven(int a){
    return ( (a & 1) == 0 );
}

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}
Michael
quelle
3
Das sieht viel sauberer aus als die akzeptierte Antwort. Dies hat nichts mit vorzeitiger Optimierung zu tun. Es ist einfach besser - wenn es funktioniert.
AlexWien
4
@LluisMartinez Dies ist eine der am häufigsten falsch zitierten Aussagen im Computer. Das vollständige Zitat lautet: "Programmierer verschwenden enorm viel Zeit damit, über die Geschwindigkeit unkritischer Teile ihrer Programme nachzudenken oder sich darüber Gedanken zu machen, und diese Effizienzversuche wirken sich tatsächlich stark negativ aus, wenn Debugging und Wartung in Betracht gezogen werden. Wir sollten kleine vergessen." Effizienz, sagen wir etwa 97% der Zeit: Vorzeitige Optimierung ist die Wurzel allen Übels. Dennoch sollten wir unsere Chancen in diesen kritischen 3% nicht verpassen. " Was eigentlich etwas ganz anderes bedeutet.
Marquis von Lorne
3
@EJP Du hast wahrscheinlich recht. Ich habe einen Test (Schleife mit 1 Million Iterationen) durchgeführt, der 4000 Nanosekunden mit Modulo, 2500 Nanosekunden mit logischen und.
Lluis Martinez
Warum sollte das eine Antwort sein? Sicher, es macht ungerade gerade, macht aber nichts mit dem Mod / Rest-Operator. Die Frage spricht über den Mod-Operator, nicht darüber, wie man ungerade gerade findet.
Mark Walsh
5
if (a % 2 == 0) {
} else {
}
JD OConal
quelle
4

In Java ist es der %Operator: 15.17.3. Restbetreiber%

Beachten Sie, dass es auch floorModin der java.lang.MathKlasse gibt, die ein anderes Ergebnis als %für Argumente mit unterschiedlichen Vorzeichen liefert:

public static int floorMod​(int x, int y)

Roland
quelle
1
Upvoted, weil floorMod ein besserer "Modulo" -Operator ist, als %da es auch richtig funktioniert, wenn das Argument ebenfalls negativ ist. Keine der anderen Antworten ist wirklich richtig, da sie den Haftungsausschluss enthalten, dass% nicht wirklich modulo ist, es sei denn, die Argumente sind positiv. Insbesondere wenn Sie jede Ganzzahl einer aufeinanderfolgenden Position in einem Array zuordnen möchten, array[floorMod(i, array.length)funktioniert dies auch dann ordnungsgemäß, wenn der Index iin den negativen Bereich wechselt. Nicht so bei %.
Kris
3

Mod kann auch so verwendet werden:

int a = 7;
b = a % 2;

bwürde gleich 1 sein. Weil 7 % 2 = 1.

jjnguy
quelle
Es ist wahrscheinlich ein Fehler, zusammengesetzte Operatoren in einem Beispiel für Anfänger und ohne Ausgabe zu verwenden.
Stu Thompson
3

Der Restoperator in Java ist %und der Modulo-Operator kann ausgedrückt werden als

public int mod(int i, int j)
{
  int rem = i % j;
  if (j < 0 && rem > 0)
  {
    return rem + j;
  }
  if (j > 0 && rem < 0)
  {
    return rem + j;
  }
  return rem;
}
Eljenso
quelle
2

Wie andere betont haben, ist der %(Rest-) Operator nicht derselbe wie die modOperation / Funktion des mathematischen Moduls.

mod vs. %

Die x mod nFunktion bildet xauf nim Bereich von [0,n).
Während der x % nBetreiber Karten xzu nim Bereich von (-n,n).

Um eine Methode zu haben, um die mathematische Moduloperation zu verwenden und sich nicht um das Vorzeichen vor xeinem zu kümmern, kann man verwenden:

((x % n) + n) % n

Vielleicht hilft dieses Bild, es besser zu verstehen (es fiel mir schwer, mich zuerst darum zu kümmern)

Geben Sie hier die Bildbeschreibung ein

m4110c
quelle
1
Schöne Zeichnung. Eine weitere Komplexität: Dies berücksichtigt nicht die 2 ^ 32-Modularität der intVariablen selbst. Die floorModMethode macht das richtig (aber wenn Sie nnegativ sind, benötigen Sie möglicherweise zusätzliche Berechnungen ).
Maarten Bodewes
1

Ein anderer Weg ist:

boolean isEven = false;
if((a % 2) == 0)
{
    isEven = true;
}

Aber der einfachste Weg ist immer noch:

boolean isEven = (a % 2) == 0;

Wie @Steve Kuo sagte.

Brüder28
quelle
0

In Javakann die Mod- Operation als solche ausgeführt werden:

Math.floorMod(a, b)

Hinweis: Die Mod- Operation unterscheidet sich von der Restoperation . In Javadem Rest kann den Betrieb als solche durchgeführt werden:

a % b
Shaun Dashjian
quelle
Nun, nicht genau ... Das Javadoc von Math.floorMod()hat es: The floor modulus is x - (floorDiv(x, y) * y), has the same sign as the divisor y, and is in the range of -abs(y) < r < +abs(y).Es ist also nicht genau das gleiche wie der mathematische Modul. Aber es gibt einen Weg, ein positives Ergebnis zu If the signs of arguments are unknown and a positive modulus is needed it can be computed as (floorMod(x, y) + abs(y)) % abs(y).
erzielen
@WesternGun Das mag wahr sein, aber wenn Sie wissen, dass der Modul positiv ist, floorModfunktioniert die Operation wie erwartet. Es gibt auch floorModfür longWerte und ansonsten BigIntegerfür größere Werte.
Maarten Bodewes
-1

Der Modulo-Operator ist% (Prozentzeichen). Um die Gleichmäßigkeit zu testen oder im Allgemeinen Modulo für eine Potenz von 2 auszuführen, können Sie auch & (den Operator und) wie isEven =! (A & 1) verwenden.

jjrv
quelle
-3

Eine Alternative zum Code von @Cody:

Verwenden des Moduloperators:

bool isEven = (a % 2) == 0;

Ich denke, dies ist ein geringfügig besserer Code als das Schreiben von if / else, da weniger Duplizierung und ungenutzte Flexibilität vorhanden sind. Es erfordert etwas mehr Gehirnleistung, um zu untersuchen, aber die gute Benennung von isEvenkompensiert.

Jay Bazuzi
quelle
2
Es ist ein Restoperator, kein Moduloperator.
Marquis von Lorne
@EJP ok. Was ist dann der Moduloperator?
TheRealChx101