Javaで2つのlong
値を追加して、結果がオーバーフローした場合に範囲にクランプされるようにするにはどうすればよいLong.MIN_VALUE
ですLong.MAX_VALUE
か。
intを追加するために、long
正確に算術演算を実行し、結果をにキャストして戻すことができますint
。例:
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;
}
また
import com.google.common.primitives.Ints;
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
return Ints.saturatedCast(sum);
}
ただしlong
、中間(クランプされていない)合計を保持できるより大きなプリミティブ型がない場合。
これはJavaであるため、インラインアセンブリ(特にSSEの飽和追加命令)を使用できません。
BigInteger
それは、例えばを使用して実装することができます
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();
}
ただし、パフォーマンスは重要であるため、この方法は理想的ではありません(ただし、テストには役立ちます)。
分岐を回避することがJavaのパフォーマンスに大きな影響を与える可能性があるかどうかはわかりません。可能だと思いますが、分岐がある場合とない場合の両方でメソッドのベンチマークを行いたいと思います。