In che modo è possibile aggiungere due valori long
in Java in modo che se il risultato trabocca, viene bloccato sull'intervallo Long.MIN_VALUE
.. Long.MAX_VALUE
?Aggiunta saturata di due valori "long" Java firmati
Per aggiungere interi si può eseguire l'aritmetica in long
precisione e gettato il risultato di nuovo ad un int
, ad esempio:
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;
}
o
import com.google.common.primitives.Ints;
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
return Ints.saturatedCast(sum);
}
ma nel caso di long
non c'è più grande tipo primitivo che può contenere la somma intermedia (non chiusa).
Dal momento che questo è Java, non posso usare inline assembly (nelle istruzioni add saturi particolare del SSE.)
Può essere implementato usando BigInteger
, per esempio
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();
}
tuttavia le prestazioni sono importanti quindi questo metodo non è ideale (anche se utile per i test.)
Io non so se evitando ramificazione può influenzare in modo significativo le prestazioni in Java. Presumo che possa, ma mi piacerebbe confrontare i metodi con e senza branching.
correlati: How to do saturating addition in C?
In realtà è possibile utilizzare l'assieme, purché lo si avvolga in JNI o JNA. Sarebbe bello vedere un punto di vista delle prestazioni tra le soluzioni proposte. – janislaw