In Java, wenn Sie dies tun
a % b
Wenn a negativ ist, wird ein negatives Ergebnis zurückgegeben, anstatt wie gewünscht um b zu wickeln. Was ist der beste Weg, um dies zu beheben? Ich kann nur denken
a < 0 ? b + a : a % b
java
modulo
negative-number
fent
quelle
quelle
Antworten:
Es verhält sich wie es sollte a% b = a - a / b * b; dh es ist der Rest.
Sie können (a% b + b)% b ausführen
Dieser Ausdruck funktioniert als Ergebnis von
(a % b)
ist notwendigerweise niedriger alsb
, egal oba
positiv oder negativ. Hinzufügenb
kümmert sich um die negativen Wertea
, da(a % b)
zwischen ein negativer Wert ist-b
und0
,(a % b + b)
ist notwendigerweise niedriger alsb
und positiv. Das letzte Modulo ista
da, fallsa
es anfangs positiv war, denn wenn es positiv ist,(a % b + b)
würde es größer werden alsb
. Daher wird(a % b + b) % b
es kleiner alsb
wieder (und wirkt sich nicht auf negativea
Werte aus).quelle
(a % b)
notwendigerweise niedriger ist alsb
(egal oba
positiv oder negativ), das Addierenb
berücksichtigt die negativen Werte vona
, da(a % b)
niedriger alsb
und niedriger als0
,(a % b + b)
notwendigerweise niedriger alsb
und positiv ist. Das letzte Modulo ista
da, fallsa
es anfangs positiv war, denn wenn es positiv ist,(a % b + b)
würde es größer werden alsb
. Daher wird(a % b + b) % b
es kleiner alsb
wieder (und wirkt sich nicht auf negativea
Werte aus).a < 0
, vielleicht könnten Sie einen Blick darauf werfen)(a % b + b) % b
für sehr große Werte vona
und zusammenbrichtb
. Wenn Sie beispielsweisea = Integer.MAX_VALUE - 1
und verwendenb = Integer.MAX_VALUE
, erhalten Sie-3
als Ergebnis eine negative Zahl, die Sie vermeiden möchten.while
wäre langsamer, wenn Sie es wirklich brauchen, außer Sie brauchen nur ein.if
In diesem Fall ist es tatsächlich schneller.Ab Java 8 können Sie Math.floorMod (int x, int y) und Math.floorMod (long x, long y) verwenden . Beide Methoden liefern die gleichen Ergebnisse wie Peters Antwort.
quelle
float
oderdouble
Argumenten. Mod binärer Operator (%
) funktioniert auch mitfloat
unddouble
Operanden.Für diejenigen, die Java 8 noch nicht verwenden (oder noch nicht verwenden können), kam Guava mit IntMath.mod () , das seit Guava 11.0 verfügbar ist , zur Rettung .
Eine Einschränkung: Im Gegensatz zu Math.floorMod () von Java 8 kann der Divisor (der zweite Parameter) nicht negativ sein.
quelle
In der Zahlentheorie ist das Ergebnis immer positiv. Ich würde vermuten, dass dies in Computersprachen nicht immer der Fall ist, da nicht alle Programmierer Mathematiker sind. Meine zwei Cent, ich würde es als Designfehler der Sprache betrachten, aber Sie können es jetzt nicht ändern.
= MOD (-4.180) = 176 = MOD (176, 180) = 176
weil 180 * (-1) + 176 = -4 das gleiche wie 180 * 0 + 176 = 176
Anhand des Uhrbeispiels hier, http://mathworld.wolfram.com/Congruence.html , würden Sie nicht sagen, dass die Dauer_der_Zeitmod-Zykluslänge -45 Minuten beträgt, sondern 15 Minuten, obwohl beide Antworten die Basisgleichung erfüllen.
quelle
-1
stattn-1
zum Beispiel). dann hab es drauf.Java 8 hat
Math.floorMod
, aber es ist sehr langsam (seine Implementierung hat mehrere Unterteilungen, Multiplikationen und eine Bedingung). Es ist jedoch möglich, dass die JVM über einen intrinsisch optimierten Stub verfügt, der sie erheblich beschleunigen würde.Der schnellste Weg, dies ohne zu tun,
floorMod
ist wie einige andere Antworten hier, aber ohne bedingte Verzweigungen und nur eine langsame%
Operation.Angenommen, n ist positiv und x kann alles sein:
Die Ergebnisse, wenn
n = 3
:Wenn Sie nur eine gleichmäßige Verteilung zwischen
0
undn-1
nicht dem exakten Mod-Operator benötigen und Ihrex
nicht in der Nähe gruppieren0
, ist das Folgende noch schneller, da mehr Parallelität auf Befehlsebene besteht und die langsame%
Berechnung parallel zum anderen erfolgt Teile, da sie nicht vom Ergebnis abhängen.return ((x >> 31) & (n - 1)) + (x % n)
Die Ergebnisse für die oben genannten mit
n = 3
:Wenn die Eingabe im gesamten Bereich eines int zufällig ist, ist die Verteilung beider beiden Lösungen gleich. Wenn sich die Eingangscluster nahe Null befinden, gibt es bei
n - 1
der letzteren Lösung zu wenige Ergebnisse .quelle
Hier ist eine Alternative:
Dies kann schneller sein oder auch nicht als die andere Formel [(a% b + b)% b]. Im Gegensatz zur anderen Formel enthält sie einen Zweig, verwendet jedoch eine Modulo-Operation weniger. Wahrscheinlich ein Gewinn, wenn der Computer eine <0 richtig vorhersagen kann.
(Bearbeiten: Die Formel wurde korrigiert.)
quelle