如何在Java中添加两个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中显著影响性能。我认为它可能会,但我想对带有和不带有分支的方法进行基准测试。
相关链接:如何在C中进行饱和加法?