Quelle est la syntaxe du mod en java

231

À titre d'exemple en pseudocode:

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

Réponses:

357

Au lieu de l'opérateur modulo, qui a une sémantique légèrement différente, pour les entiers non négatifs, vous pouvez utiliser l' opérateur restant% . Pour votre exemple exact:

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

Cela peut être simplifié en une seule ligne:

isEven = (a % 2) == 0;
Cody Hatch
la source
80
Le if / else n'est pas nécessaire, utilisez simplement isEven = (a% 2) == 0,
Steve Kuo
59
Attention aux termes mod et modulaire car n (mod m) EST TOUJOURS> = 0 mais pas n% m. n% m est dans la plage> -m et <m. Bien que Java ait un opérateur de reste pour les types int et long, il n'a ni fonction ni opérateur de module. C'est-à-dire, -12% 10 = -2 tandis que -12 mod 10 = 8. Si l'opérateur% renvoie une valeur négative pour n% m, alors (n% m) + m vous donnera n mod m. BigInteger fournit des fonctions pour les deux et leurs spécifications expliquent assez bien la différence. Aussi, attention à zéro. En mathématiques, bien que zéro soit un nombre pair, il n'est PAS positif ou négatif.
Jim
4
@ nl-x Probablement parce qu'il vaut mieux être explicite sur la priorité que de le laisser à la convention. Pour ma part, je ne savais pas que cela %était évalué avant de le ==rechercher, il serait donc difficile de savoir si l'expression est équivalente à (a%2)==0ou a%(2==0). Je suppose que c'est moins important en java où un booléen n'est pas le même qu'un entier
Matthew Sainsbury
8
Ce n'est pas l'opérateur module - c'est l'opérateur restant. Veuillez corriger le message!
Kieren Johnstone
2
booléen pair = ((a & 1) == 0). Beaucoup plus facile.
mdev
111

Voici la représentation de votre pseudo-code en code Java minimal;

boolean isEven = a % 2 == 0;

Je vais maintenant le décomposer en ses composants. L'opérateur de module en Java est le pourcentage (%). Par conséquent, prendre un int% int renvoie un autre int. L'opérateur double égal (==) est utilisé pour comparer des valeurs, telles qu'une paire d'entiers et renvoie un booléen. Ceci est ensuite affecté à la variable booléenne 'isEven'. En fonction de la priorité de l'opérateur, le module sera évalué avant la comparaison.

martinatime
la source
12
minimal serait sans les crochets;)
pstanton
3
C'est un opérateur de reste, pas un opérateur de module.
Marquis de Lorne
@ user207421 Son nom est en fait opérateur restant mais ne sont-ils pas équivalents: " module - 4. (informatique, programmation) Un opérateur placé entre deux nombres, pour obtenir le reste de la division de ces nombres."?
GeroldBroser réintègre Monica
93

Puisque tout le monde a déjà donné la réponse, je vais ajouter un peu de contexte supplémentaire. % l'opérateur "module" effectue actuellement l'opération restante. La différence entre mod et rem est subtile, mais importante.

(-1 mod 2) donnerait normalement 1. Plus spécifiquement, étant donné deux entiers, X et Y, l'opération (X mod Y) tend à renvoyer une valeur dans la plage [0, Y). Autrement dit, le module de X et Y est toujours supérieur ou égal à zéro, et inférieur à Y.

L'exécution de la même opération avec l'opérateur "%" ou rem conserve le signe de la valeur X. Si X est négatif, vous obtenez un résultat dans la plage (-Y, 0]. Si X est positif, vous obtenez un résultat dans la plage [0, Y).

Souvent, cette distinction subtile n'a pas d'importance. Pour en revenir à votre question de code, cependant, il existe plusieurs façons de résoudre le problème de "régularité".

La première approche est bonne pour les débutants, car elle est particulièrement verbeuse.

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

La deuxième approche tire mieux parti du langage et conduit à un code plus succinct. (N'oubliez pas que l'opérateur == renvoie un booléen.)

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

La troisième approche est ici pour l'exhaustivité et utilise l' opérateur ternaire . Bien que l'opérateur ternaire soit souvent très utile, dans ce cas, je considère la deuxième approche comme supérieure.

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

La quatrième et dernière approche consiste à utiliser la connaissance de la représentation binaire des nombres entiers . Si le bit le moins significatif est 0, alors le nombre est pair. Cela peut être vérifié à l'aide de l' opérateur au niveau du bit et (&). Bien que cette approche soit la plus rapide (vous faites du masquage de bits simple au lieu de la division), elle est peut-être un peu avancée / compliquée pour un débutant.

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

Ici, j'ai utilisé l'opérateur bit à bit et et je l'ai représenté sous la forme succincte illustrée dans l'option 2. La réécrire sous la forme de l'option 1 (et alternativement de l'option 3) est laissée au lecteur comme exercice. ;)

J'espère que cela pourra aider.

Rob Rolnick
la source
Merci Rob. Cette confusion entraîne d'énormes difficultés à expliquer aux programmeurs comment implémenter des algorithmes avec des propriétés mathématiques à partir de l'arithmétique modulaire. Le reste n'est PAS un module mais on peut rapidement dériver un module des restes.
Jim
1
@TickledPink Sauf que cela ne se compile pas en Java.
Eugene Beresovsky
33

Pour que l'opération% (REM) de Java fonctionne comme MOD pour les valeurs X négatives et Y positives, vous pouvez utiliser cette méthode:

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

ou avec l'opérateur ternaire (plus court, mais pas possible ou moins efficace dans certaines situations):

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

Java n'a en fait pas d'opérateur modulo comme le fait C. % en Java est un opérateur restant. Sur les entiers positifs, il fonctionne exactement comme modulo, mais il fonctionne différemment sur les entiers négatifs et, contrairement à modulo, peut également fonctionner avec des nombres à virgule flottante. Pourtant, il est rare d'utiliser% sur autre chose que des entiers positifs, donc si vous voulez l'appeler un modulo, alors n'hésitez pas!

Greg Charles
la source
Mais je veux que l'on soit un véritable opérateur modulo qui fonctionne aussi pour les entiers négatifs afin que array[x mod array.length]toujours accède à un élément de mon tableau plutôt que d'essayer d'indexer les positions négatives.
Kris
2
(x % y + y) % y ou à partir de Java 8,Math.floorMod(x, y)
Greg Charles
12

Bien qu'il soit possible de faire un modulo approprié en vérifiant si la valeur est négative et en la corrigeant si elle l'est (comme beaucoup l'ont suggéré), il existe une solution plus compacte.

(a % b + b) % b

Cela fera d'abord le modulo, en limitant la valeur à la plage -b -> + b, puis ajoutera b afin de garantir que la valeur est positive, laissant le modulo suivant la limiter à la plage 0 -> b.

Remarque: si b est négatif, le résultat sera également négatif

Stefan T
la source
Cela peut déborder lorsque a et b sont tous deux de grands nombres, donc ce n'est pas une solution correcte.
Trixie Wolf,
11

Le code s'exécute beaucoup plus rapidement sans utiliser modulo:

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

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}
Michael
la source
3
Cela semble beaucoup plus propre que la réponse acceptée. Cela n'a rien à voir avec une optimisation prématurée. C'est tout simplement mieux, - si cela fonctionne.
AlexWien
4
@LluisMartinez C'est l'un des dictons les plus mal cités de l'informatique. La citation complète est: "Les programmeurs perdent énormément de temps à penser ou à s'inquiéter de la vitesse des parties non critiques de leurs programmes, et ces tentatives d'efficacité ont en fait un fort impact négatif lorsque le débogage et la maintenance sont envisagés. Nous devons oublier les petits efficacité, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal. Pourtant, nous ne devons pas laisser passer nos opportunités dans ces 3% critiques. ". Ce qui signifie en fait quelque chose de très différent.
Marquis de Lorne
3
@EJP Vous avez probablement raison. J'ai fait un test (boucle avec 1 million d'itérations) a pris 4000 nanosecondes avec modulo, 2500 nanosecondes avec logique et.
Lluis Martinez
Pourquoi serait-ce une réponse? Bien sûr, il fait impair même, mais ne fait rien avec l'opérateur mod / reste. La question parle de l'opérateur de mod, pas de la façon de trouver un pair pair.
Mark Walsh
5
if (a % 2 == 0) {
} else {
}
JD OConal
la source
4

En Java, c'est l' %opérateur: 15.17.3. Opérateur restant%

Notez qu'il y a aussi floorModdans la java.lang.Mathclasse qui donnera un résultat différent de %pour les arguments avec des signes différents:

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

Roland
la source
1
Voté, car floorMod est un meilleur opérateur «modulo» que %car il fonctionne également correctement lorsque l'argument est également négatif. Aucune des autres réponses n'est vraiment correcte car elles sont accompagnées de la clause de non-responsabilité selon laquelle% n'est pas vraiment modulo, sauf si les arguments sont positifs. En particulier, si vous souhaitez mapper chaque entier à une position consécutive dans un tableau, il array[floorMod(i, array.length)fonctionne correctement même si l'index ipasse en territoire négatif. Pas avec %.
Kris
3

De plus, le mod peut être utilisé comme ceci:

int a = 7;
b = a % 2;

bserait égal à 1. Parce que 7 % 2 = 1.

jjnguy
la source
c'est probablement une erreur d'utiliser des opérateurs composés dans un exemple pour les débutants, et sans sortie.
Stu Thompson
3

L'opérateur restant en Java est %et l'opérateur modulo peut être exprimé comme

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
la source
2

Comme d'autres l'ont souligné, l' %opérateur (restant) n'est pas le même que l' modopération / la fonction du module mathématique .

mod contre %

La x mod nfonction correspond xà ndans la plage de [0,n).
Alors que les x % ncartes opérateur xà nl'ordre de (-n,n).

Afin d'avoir une méthode pour utiliser l'opération de module mathématique et ne pas se soucier du signe devant xon peut utiliser:

((x % n) + n) % n

Peut-être que cette image aide à mieux la comprendre (j'ai eu du mal à envelopper ma tête autour de cette première)

entrez la description de l'image ici

m4110c
la source
1
Joli dessin. Autre complexité: cela ne prend pas en compte la modularité 2 ^ 32 de la intvariable elle-même. La floorModméthode le fait correctement (mais vous pouvez avoir besoin de calculs supplémentaires si elle nest négative).
Maarten Bodewes
1

Une autre façon est:

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

Mais le moyen le plus simple reste:

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

Comme l'a dit @Steve Kuo.

frères28
la source
0

Dans Java, l' opération de mod peut être effectuée comme telle:

Math.floorMod(a, b)

Remarque: L' opération mod est différente de l' opération restante . Dans Java, l' opération restante peut être effectuée comme telle:

a % b
Shaun Dashjian
la source
Eh bien pas exactement ... Le javadoc de l' Math.floorMod()a: 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).Donc ce n'est pas exactement le même que le module mathématique. Mais , il existe un moyen d'obtenir un résultat positif, également dans le Javadoc de la même méthode: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 Cela peut être vrai, mais si vous savez que le module est positif, l' floorModopération fonctionne comme prévu. Il y a aussi les valeurs floorModfor longet sinon il y a BigIntegerdes valeurs plus grandes.
Maarten Bodewes
-1

L'opérateur modulo est% (signe pourcentage). Pour tester la régularité ou généralement modulo pour une puissance de 2, vous pouvez également utiliser & (l'opérateur et) comme isEven =! (A & 1).

jjrv
la source
-3

Une alternative au code de @Cody:

Utilisation de l'opérateur module:

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

Je pense que c'est un code légèrement meilleur que d'écrire if / else, car il y a moins de duplication et de flexibilité inutilisée. Cela nécessite un peu plus de puissance cérébrale à examiner, mais la bonne dénomination de isEvencompense.

Jay Bazuzi
la source
2
C'est un opérateur de reste, pas un opérateur de module.
Marquis de Lorne
@EJP ok. Alors, quel est l'opérateur de module?
TheRealChx101