¿Cómo se pueden agregar dos valores de long
en Java para que, si el resultado se desborda, se fije en el rango Long.MIN_VALUE
.. Long.MAX_VALUE
?Adición saturada de dos valores 'largos' de Java firmados
Para añadir ints uno puede realizar la aritmética en long
precisión y emitir el resultado de nuevo a un int
, por ejemplo:
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);
}
pero en el caso de long
no hay tipo primitivo más grande que puede contener la suma intermedia (no bloqueada).
Dado que este es Java, no puedo usar inline assembly (en las instrucciones add saturados en particular de SSE.)
Se puede implementar usando BigInteger
, por ejemplo
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();
}
sin embargo el rendimiento es importante por lo que este método no es ideal (aunque útiles para la prueba.)
No sé si se puede evitar la ramificación afectar significativamente al rendimiento en Java. Supongo que sí, pero me gustaría comparar los métodos con y sin ramificación.
relacionadas: How to do saturating addition in C?
En realidad puede usar el conjunto, siempre que lo envuelva en JNI o JNA. Sería genial ver una relación rendimiento-sabio entre las soluciones propuestas. – janislaw