Wie kann man zwei long
Werte in Java hinzufügen, so dass, wenn das Ergebnis überläuft, es in den Bereich Long.MIN_VALUE
.. Long.MAX_VALUE
geklemmt wird?Gesättigte Addition von zwei signierten Java-Long-Werten
Für ints Zugabe kann man die arithmetische in long
Präzision durchzuführen und das Ergebnis zurück in ein int
gegossen, zum Beispiel:
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
long clampedSum = Math.max((long) Integer.MIN_VALUE,
Math.min(sum, (long) Integer.MAX_VALUE));
return (int) clampedSum;
}
oder
import com.google.common.primitives.Ints;
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
return Ints.saturatedCast(sum);
}
aber im Fall von long
es keine größerer primitiver Typ, der die Zwischensumme (nicht geklammerte Summe) enthalten kann.
Da es sich um Java, kann ich nicht inline assembly verwenden (insbesondere gesättigte des SSE Add Anweisungen.)
Es implementiert werden kann BigInteger
, z.B.
static final BigInteger bigMin = BigInteger.valueOf(Long.MIN_VALUE);
static final BigInteger bigMax = BigInteger.valueOf(Long.MAX_VALUE);
long saturatedAdd(long x, long y) {
BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y));
return bigMin.max(sum).min(bigMax).longValue();
}
aber Leistung ist wichtig, so dass diese Methode nicht ideal ist (wenn auch nützlich für die Prüfung.)
Ich weiß nicht, ob Verzweigung vermieden die Leistung erheblich in Java beeinflussen kann. Ich nehme an, dass es möglich ist, aber ich möchte Methoden mit und ohne Verzweigung benchmarken.
Verwandte: How to do saturating addition in C?
Eigentlich können Sie die Assembly verwenden, sofern Sie sie in JNI oder JNA einbinden. Es wäre großartig, wenn man die vorgeschlagenen Lösungen in Bezug auf die Leistung sehen würde. – janislaw