En java quand vous le faites
a % b
Si a est négatif, il renverra un résultat négatif, au lieu de revenir à b comme il se doit. Quelle est la meilleure façon de résoudre ce problème? La seule façon dont je peux penser est
a < 0 ? b + a : a % b
En java quand vous le faites
a % b
Si a est négatif, il renverra un résultat négatif, au lieu de revenir à b comme il se doit. Quelle est la meilleure façon de résoudre ce problème? La seule façon dont je peux penser est
a < 0 ? b + a : a % b
Réponses:
Il se comporte comme il se doit a% b = a - a / b * b; c'est à dire que c'est le reste.
Vous pouvez faire (a% b + b)% b
Cette expression fonctionne comme le résultat de
(a % b)
est nécessairement inférieur àb
, peu importe sia
est positif ou négatif. L'ajoutb
prend en charge les valeurs négatives dea
, puisque(a % b)
est une valeur négative entre-b
et0
,(a % b + b)
est nécessairement inférieure àb
et positive. Le dernier modulo est là au cas oùa
était positif au départ, car sia
est positif(a % b + b)
deviendrait plus grand queb
. Par conséquent, le(a % b + b) % b
transforme en plus petit que deb
nouveau (et n'affecte pas lesa
valeurs négatives ).la source
(a % b)
est nécessairement inférieur àb
(peu importe s'ila
est positif ou négatif), l'additionb
prend en charge les valeurs négatives dea
, car(a % b)
est inférieur àb
et inférieur à0
,(a % b + b)
est nécessairement inférieur àb
et positif. Le dernier modulo est là au cas oùa
était positif au départ, car sia
est positif(a % b + b)
deviendrait plus grand queb
. Par conséquent, le(a % b + b) % b
transforme en plus petit queb
nouveau (et n'affecte pas lesa
valeurs négatives ).a < 0
, peut-être que vous pourriez y jeter un coup d'œil)(a % b + b) % b
se décompose pour les très grandes valeurs dea
etb
. Par exemple, utilisera = Integer.MAX_VALUE - 1
etb = Integer.MAX_VALUE
donnera-3
comme résultat, qui est un nombre négatif, ce que vous vouliez éviter.while
serait plus lent si vous en avez vraiment besoin, sauf que vous n'avez besoin que d'un,if
auquel cas il est en fait plus rapide.A partir de Java 8, vous pouvez utiliser Math.floorMod (int x, int y) et Math.floorMod (long x, long y) . Ces deux méthodes renvoient les mêmes résultats que la réponse de Peter.
la source
float
oudouble
arguments. L'opérateur binaire Mod (%
) fonctionne également avec les opérandesfloat
etdouble
.Pour ceux qui n'utilisent pas (ou ne peuvent pas encore utiliser) Java 8, Guava est venu à la rescousse avec IntMath.mod () , disponible depuis Guava 11.0.
Une mise en garde: contrairement à Math.floorMod () de Java 8, le diviseur (le deuxième paramètre) ne peut pas être négatif.
la source
En théorie des nombres, le résultat est toujours positif. Je suppose que ce n'est pas toujours le cas dans les langages informatiques car tous les programmeurs ne sont pas des mathématiciens. Mes deux cents, je considérerais cela comme un défaut de conception du langage, mais vous ne pouvez pas le changer maintenant.
= MOD (-4 180) = 176 = MOD (176, 180) = 176
car 180 * (-1) + 176 = -4 identique à 180 * 0 + 176 = 176
En utilisant l'exemple d'horloge ici, http://mathworld.wolfram.com/Congruence.html vous ne diriez pas que duration_of_time mod cycle_length est de -45 minutes, vous diriez 15 minutes, même si les deux réponses satisfont l'équation de base.
la source
-1
au lieu de,n-1
par exemple) alors ayez à lui.Java 8 a
Math.floorMod
, mais il est très lent (son implémentation a plusieurs divisions, multiplications et un conditionnel). Cependant, il est possible que la JVM dispose d'un stub intrinsèque optimisé, ce qui l'accélérerait considérablement.Le moyen le plus rapide de faire cela sans
floorMod
est comme d'autres réponses ici, mais sans branches conditionnelles et une seule opération lente%
.En supposant que n est positif et que x peut être n'importe quoi:
Les résultats lorsque
n = 3
:Si vous avez seulement besoin d 'une distribution uniforme entre
0
etn-1
et non l' opérateur de mod exact, et que vosx
ne se regroupent pas près0
, ce qui suit sera encore plus rapide, car il y a plus de parallélisme au niveau des instructions et le%
calcul lent se produira en parallèle avec l 'autre pièces car elles ne dépendent pas de son résultat.return ((x >> 31) & (n - 1)) + (x % n)
Les résultats pour ce qui précède avec
n = 3
:Si l'entrée est aléatoire dans la plage complète d'un entier, la distribution des deux solutions sera la même. Si les grappes d'entrée sont proches de zéro, il y aura trop peu de résultats
n - 1
dans cette dernière solution.la source
Voici une alternative:
Cela pourrait ou non être plus rapide que cette autre formule [(a% b + b)% b]. Contrairement à l'autre formule, elle contient une branche, mais utilise une opération modulo en moins. Probablement une victoire si l'ordinateur peut prédire correctement un <0.
(Edit: Correction de la formule.)
la source