[英]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);
那么,是否意味着逻辑右移将考虑溢出位?
你是正确的,表达式将溢出为足够大的low
和high
值。 如果其中一个值为负,则可能会得到错误的结果。
但是,在二进制搜索方法中不能得到负数,因为low
和high
都是数组的索引; 他们必须是积极的。 因此,加法的结果只会溢出到符号位; 它不会创建一个进位。
由于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.