繁体   English   中英

Java,会(低+高)>>> 1溢出?

[英]Java, will (low + high) >>> 1 overflow?

我在看Java 1.8 Api。 java.util.Arrays.binarySearch(int[] a, int key) ,我找到了这段代码。

int low = fromIndex;
int high = toIndex - 1;

while (low <= high) {
    int mid = (low + high) >>> 1;
    int midVal = a[mid];

    if (midVal < key)
        low = mid + 1;
    else if (midVal > key)
        high = mid - 1;
    else
        return mid; // key found
}
return -(low + 1);  // key not found.

在这段代码中(low + high) >>> 1不会溢出。 谁能告诉我为什么会这样? 我用我自己的代码测试它。

int low = Integer.MAX_VALUE;
int high = Integer.MAX_VALUE;
System.out.println((low + high) / 2);
System.out.println((low + high) >>> 1);

那么,是否意味着逻辑右移将考虑溢出位?

你是正确的,表达式将溢出为足够大的lowhigh值。 如果其中一个值为负,则可能会得到错误的结果。

但是,在二进制搜索方法中不能得到负数,因为lowhigh都是数组的索引; 他们必须是积极的。 因此,加法的结果只会溢出到符号位; 它不会创建一个进位。

由于Java的>>>运算符将在没有符号扩展的情况下移位符号位,因此即使对于两个Integer.MAX_VALUE ,也会得到正确的结果。 本质上, >>>运算符允许您将第32位视为无符号存储的额外位,即使该位属于有符号类型。

如果low + high的结果溢出并变为负,则(low + high) / 2(low + high) >> 1都不起作用。

a >> 1保持原有的符号位,所以对于负值a为负结果

a >>> 1通过引入零符号位来工作,因此任何a的结果都不能为负。

示范:

int low = 1;
int high = Integer.MAX_VALUE;
System.out.println(low + high);         // This is negative
System.out.println((low + high) >>> 1); // This is positive, and the desired result.
System.out.println((low + high) >> 1);  // This is negative
System.out.println((low + high) / 2);   // This is negative

由于溢出,找到两个int值的中间值很容易出错。 对于适用于正值和负值的表达式,请参阅此问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM