两个整数(或多头)没有溢出的平均值,截断为0

时间:2013-04-20 01:11:19

标签: java math overflow bit-manipulation

我想在Java中为任意两个整数x,y计算(x + y)/2。如果x + y> 0,则天真的方式会遇到问题。 Integer.MAX_VALUE或< Integer.MIN_VALUE的。

番石榴IntMath uses这种技巧:

  public static int mean(int x, int y) {
    // Efficient method for computing the arithmetic mean.
    // The alternative (x + y) / 2 fails for large values.
    // The alternative (x + y) >>> 1 fails for negative values.
    return (x & y) + ((x ^ y) >> 1);
  }

...但是这会向负无穷大方向发展,这意味着例程不符合像{-1,-2}这样的值的天真方式(给-2而不是-1)。

是否有任何相应的例程向0截断?

“只使用long”不是我正在寻找的答案,因为我想要一个适用于长输入的方法。 BigInteger也不是我正在寻找的答案。我不想要任何分支机构的解决方案。

2 个答案:

答案 0 :(得分:2)

如果最低位不同(因此结果不准确且需要舍入),则需要将1添加到结果中,并且结果中的符号位置位(结果为负,所以你想把这一轮改成圆形)。

所以以下内容应该(未经测试):

public static int mean(int x, int y) {
    int xor = x ^ y;
    int roundedDown = (x & y) + (xor >> 1);
    return roundedDown + (1 & xor & (roundedDown >>> 31));
}

答案 1 :(得分:0)

为什么不执行(x-y)/2 + y之类的操作,缩减为x/2 - y/2 + y = x/2 + y/2?因此,如果x+y为您提供上溢或下溢,请以(x-y)/2 + y方式执行此操作。