Qual è la sintassi per mod in Java


231

Ad esempio in pseudocodice:

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

Risposte:


357

Invece dell'operatore modulo, che ha una semantica leggermente diversa, per numeri interi non negativi, è possibile utilizzare l' operatore residuo% . Per il tuo esempio esatto:

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

Questo può essere semplificato in una riga:

isEven = (a % 2) == 0;

80
L'if / se non è necessario, basta usare isEven = (a% 2) == 0,
Steve Kuo,

59
Attento ai termini mod e modular perché n (mod m) È SEMPRE> = 0 ma non n% m. n% m è compreso nell'intervallo> -m e <m. Sebbene Java abbia un operatore residuo per i tipi int e long, non ha alcuna funzione o operatore modulo. Cioè, -12% 10 = -2 mentre -12 mod 10 = 8. Se l'operatore% restituisce un valore negativo per n% m, allora (n% m) + m ti darà n mod m. BigInteger fornisce funzioni per entrambi e le specifiche spiegano abbastanza bene la differenza. Inoltre, fai attenzione con zero. In matematica, mentre zero è un numero pari NON è positivo o negativo.
Jim,

4
@ nl-x Probabilmente perché è meglio essere espliciti sulla precedenza piuttosto che lasciarlo alla convenzione. Io per primo non sapevo che %fosse valutato prima di ==cercarlo, quindi non sarebbe chiaro se l'espressione sia equivalente a (a%2)==0o a%(2==0). Immagino sia meno importante in Java dove un booleano non è uguale a un intero
Matthew Sainsbury,

8
Questo non è l'operatore del modulo, è l'operatore residuo. Per favore correggi il post!
Kieren Johnstone,

2
booleano even = ((a & 1) == 0). Molto più facile.
mdev,

111

Ecco la rappresentazione del tuo pseudo-codice in un codice Java minimo;

boolean isEven = a % 2 == 0;

Ora lo scompongo nei suoi componenti. L'operatore del modulo in Java è il carattere percentuale (%). Pertanto, prendere un int% int restituisce un altro int. L'operatore double equals (==) viene utilizzato per confrontare valori, come una coppia di ints e restituisce un valore booleano. Questo viene quindi assegnato alla variabile booleana 'isEven'. In base alla precedenza dell'operatore, il modulo verrà valutato prima del confronto.


12
il minimo sarebbe senza parentesi;)
pstanton,

3
È un operatore residuo, non un operatore modulo.
Marchese di Lorne,

@ user207421 Il suo nome è in effetti operatore residuo ma non sono equivalenti: " modulo - 4. (elaborazione, programmazione) Un operatore posizionato tra due numeri, per ottenere il resto della divisione di quei numeri."?
GeroldBroser ripristina Monica

93

Poiché tutti gli altri hanno già dato la risposta, aggiungerò un po 'di contesto aggiuntivo. % l'operatore "modulo" sta effettivamente eseguendo l'operazione rimanente. La differenza tra mod e rem è sottile, ma importante.

(-1 mod 2) normalmente darebbe 1. Più specificatamente dati due numeri interi, X e Y, l'operazione (X mod Y) tende a restituire un valore nell'intervallo [0, Y). Detto diversamente, il modulo di X e Y è sempre maggiore o uguale a zero e minore di Y.

L'esecuzione della stessa operazione con "%" o l'operatore rem mantiene il segno del valore X. Se X è negativo si ottiene un risultato nell'intervallo (-Y, 0]. Se X è positivo si ottiene un risultato nell'intervallo [0, Y).

Spesso questa sottile distinzione non ha importanza. Tornando alla domanda sul codice, tuttavia, ci sono diversi modi per risolvere "uniformità".

Il primo approccio è buono per i principianti, perché è particolarmente prolisso.

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

Il secondo approccio sfrutta meglio il linguaggio e porta a un codice più conciso. (Non dimenticare che l'operatore == restituisce un valore booleano.)

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

Il terzo approccio è qui per completezza e utilizza l' operatore ternario . Sebbene l'operatore ternario sia spesso molto utile, in questo caso considero superiore il secondo approccio.

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

Il quarto e ultimo approccio consiste nell'utilizzare la conoscenza di rappresentazione binaria di numeri interi . Se il bit meno significativo è 0, il numero è pari. Questo può essere verificato usando l' operatore bit-bit (&). Mentre questo approccio è il più veloce (stai facendo un semplice mascheramento dei bit invece della divisione), è forse un po 'avanzato / complicato per un principiante.

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

Qui ho usato l'operatore bit per bit e l'ho rappresentato nella forma sintetica mostrata nell'opzione 2. La riscrittura nella forma dell'opzione 1 (e in alternativa dell'opzione 3) è lasciata come esercizio al lettore. ;)

Spero che aiuti.


Grazie Rob. Questa confusione causa enormi difficoltà a spiegare ai programmatori come implementare algoritmi con proprietà matematiche dall'aritmetica modulare. Il resto NON è un modulo ma si può derivare rapidamente un modulo dai resti.
Jim,

1
@TickledPink Ad eccezione del fatto che questo non viene compilato in Java.
Eugene Beresovsky

33

Per far funzionare l'operazione% (REM) di Java come MOD per valori X e Y positivi Y, è possibile utilizzare questo metodo:

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

o con l'operatore ternario (più breve, ma non possibile o meno efficiente in alcune situazioni):

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

12

Java in realtà non ha un operatore modulo come fa C. % in Java è un operatore rimanente. Sugli interi positivi, funziona esattamente come il modulo, ma funziona in modo diverso sugli interi negativi e, a differenza del modulo, può funzionare anche con numeri in virgola mobile. Tuttavia, è raro usare% su tutto tranne che sugli interi positivi, quindi se vuoi chiamarlo un modulo, sentiti libero!


Ma ne voglio uno un vero operatore modulo che funzioni anche per numeri interi negativi in ​​modo che array[x mod array.length]acceda sempre a un elemento nel mio array piuttosto che cercare di indicizzare posizioni negative.
Kris

2
(x % y + y) % y o a partire da Java 8,Math.floorMod(x, y)
Greg Charles,

12

Mentre è possibile fare un modulo corretto controllando se il valore è negativo e correggerlo se lo è (come molti hanno suggerito), esiste una soluzione più compatta.

(a % b + b) % b

Questo farà prima il modulo, limitando il valore all'intervallo -b -> + b, quindi aggiungendo b per garantire che il valore sia positivo, lasciando che il modulo successivo lo limiti all'intervallo 0 -> b.

Nota: se b è negativo, anche il risultato sarà negativo


Questo può traboccare quando aeb sono entrambi numeri grandi, quindi non è una soluzione corretta.
Trixie Wolf,

11

Il codice funziona molto più velocemente senza usare modulo:

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

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

3
Sembra molto più pulito della risposta accettata. Questo non ha nulla a che fare con l'ottimizzazione prematura. È semplicemente meglio, se funziona.
AlexWien,

4
@LluisMartinez Questo è uno dei detti più citati nell'informatica. La citazione completa è "I programmatori sprecano enormi quantità di tempo pensando o preoccupandosi della velocità delle parti non critiche dei loro programmi, e questi tentativi di efficienza hanno effettivamente un forte impatto negativo quando si considerano il debug e la manutenzione. efficienze, dicono circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutti i mali. Eppure non dovremmo rinunciare alle nostre opportunità in quel 3% critico ". Il che in realtà significa qualcosa di completamente diverso.
Marchese di Lorne,

3
@EJP Probabilmente hai ragione. Ho fatto un test (loop con 1 milione di iterazioni) ho impiegato 4000 nanosecondi con modulo, 2500 nanosecondi con logico e.
Lluis Martinez,

Perché questa dovrebbe essere una risposta? Sicuro che dispari anche, ma non fa nulla con l'operatore mod / remainder. La domanda parla dell'operatore mod, non di come trovare pari dispari.
Mark Walsh,



4

In Java è l' %operatore: 15.17.3. Operatore residuo%

Nota che c'è anche floorModnella java.lang.Mathclasse che darà un risultato diverso da %per argomenti con segni diversi:

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


1
Eseguito l'upgrade, perché floorMod è un operatore 'modulo' migliore rispetto %a quando funziona correttamente anche quando l'argomento è negativo. Nessuna delle altre risposte è davvero corretta poiché presentano la dichiarazione di non responsabilità che% non è realmente modulo a meno che gli argomenti non siano positivi. In particolare, se si desidera mappare ogni numero intero su una posizione consecutiva in un array, allora array[floorMod(i, array.length)funziona correttamente anche se l'indice iva in territorio negativo. Non così con %.
Kris

3

Inoltre, la mod può essere utilizzata in questo modo:

int a = 7;
b = a % 2;

bequivarrebbe a 1. Perché 7 % 2 = 1.


è probabilmente un errore usare operatori composti in un esempio per principianti e senza output.
Stu Thompson,

3

L'operatore residuo in Java è %e l'operatore modulo può essere espresso come

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

2

Come altri hanno sottolineato, l' %operatore (resto) non è lo stesso moddell'operazione / funzione del modulo matematico .

mod vs %

La x mod nfunzione di mappe xper nla gamma di [0,n).
Considerando che l' x % noperatore di mappe xper nla gamma di (-n,n).

Per avere un metodo per usare l'operazione del modulo matematico e non preoccuparsi del segno davanti a xuno, puoi usare:

((x % n) + n) % n

Forse questa foto aiuta a capirla meglio (ho avuto difficoltà a avvolgere la mia testa per prima)

inserisci qui la descrizione dell'immagine


1
Bel disegno. Un'altra complessità: ciò non tiene conto della modularità 2 ^ 32 della intvariabile stessa. Il floorModmetodo lo fa correttamente (ma potresti aver bisogno di calcoli aggiuntivi se nè negativo).
Maarten Bodewes,

1

Un altro modo è:

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

Ma il modo più semplice è ancora:

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

Come ha detto @Steve Kuo.


0

In Java, l' operazione mod può essere eseguita come tale:

Math.floorMod(a, b)

Nota: l' operazione mod è diversa dall'operazione rimanente . In Java, l' operazione rimanente può essere eseguita come tale:

a % b

Beh, non esattamente ... Il javadoc ce l' Math.floorMod()ha: 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).Quindi non è esattamente lo stesso del modulo matematico. Ma c'è un modo per ottenere un risultato positivo, anche nel Javadoc dello stesso metodo: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).
WesternGun

@WesternGun Questo può essere vero, ma se sai che il modulo è positivo, l' floorModoperazione funziona come previsto. C'è anche il floorModper i longvalori e altrimenti c'è BigIntegerper i valori più grandi.
Maarten Bodewes,

-1

L'operatore modulo è% (segno di percentuale). Per verificare l'uniformità o in generale fare modulo per una potenza di 2, puoi anche usare & (l'operatore e) come isEven =! (A & 1).


-3

Un'alternativa al codice di @Cody:

Utilizzando l'operatore modulo:

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

Penso che questo sia un codice leggermente migliore rispetto alla scrittura if / else, perché c'è meno duplicazione e flessibilità inutilizzata. Richiede un po 'più di potenza cerebrale da esaminare, ma la buona denominazione di isEvencompensa.


2
È un operatore residuo, non un operatore modulo.
Marchese di Lorne,

@EJP ok. Allora qual è l'operatore del modulo?
TheRealChx101
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.