[英]Java, will (low + high) >> 1 overflow?
I know that >>
is for signed and >>>
is for unsigned我知道
>>
用于已签名,而>>>
用于未签名
Similar questions that do not answer my question:没有回答我的问题的类似问题:
Java, will (low + high) >>> 1 overflow? Java,会(低+高)>>> 1 溢出吗?
Safe integer middle value formula 安全整数中值公式
According to the second link, why do they conclude that: avg = (low & high) + ((low ^ high) >> 1);
根据第二个链接,他们为什么得出结论:
avg = (low & high) + ((low ^ high) >> 1);
will avoid overflow?会避免溢出吗?
Why can't they just use this instead : (low + high) >> 1
?为什么他们不能直接使用它 :
(low + high) >> 1
?
(This is for binary search in java) (这是用于java中的二进制搜索)
Yes, (low + high) >> 1
may overflow if the sum is high enough.是的,
(low + high) >> 1
如果总和足够高,可能会溢出。 As you know, >>>
is for unsigned, so that it will always shift in a 0
on the most significant side.如您所知,
>>>
用于无符号,因此它始终会在最重要的一侧移动0
。 This turns out to be very important in case it does overflow.事实证明,这在它确实溢出时非常重要。
The trick to using (low + high)
even with overflow is that information is still retained.即使有溢出,使用
(low + high)
的技巧是仍然保留信息。 If it does overflow, the maximum possible mathematical sum is still Integer.MAX_VALUE * 2
, which would still be representable as an unsigned int
, if Java had one.如果它确实溢出,最大可能的数学总和仍然是
Integer.MAX_VALUE * 2
,如果 Java 有一个 unsigned int
,它仍然可以表示为 unsigned int
。 But we can treat the sum as an unsigned int when dividing by 2 by using the unsigned right shift operator, >>>
.但是,再除以2,当使用无符号向右移位运算,我们可以把之作为一个unsigned int,
>>>
。 When bit-shifting to the right by 1
, this lets us treat the sum as an unsigned int
, "un-overflowing" the int
.当右移
1
,这让我们将总和视为 unsigned int
,“不溢出” int
。
Using >>
here won't work if the sum overflows, because it will overflow into a negative number and >>
will shift in a 1
, keeping the value negative.如果总和溢出,在此处使用
>>
将不起作用,因为它将溢出为负数,而>>
将移入1
,从而使值保持为负。 This results in an incorrect average calculation (2 positive numbers whose sum overflows will result in a negative average).这会导致不正确的平均值计算(2 个正数的总和溢出将导致负平均值)。
Whether you're using >>>
or >>
, overflow is a possibility.无论您使用的是
>>>
还是>>
,都有可能发生溢出。 So both can overflow.所以两者都可以溢出。 But only
>>>
will handle the case well, properly "un-overflowing" the sum.但只有
>>>
才能很好地处理这个案子,正确地“不溢出”总和。
The trick诀窍
avg = (low & high) + ((low ^ high) >> 1);
is another way calculating the average when the sum may overflow.是在总和可能溢出时计算平均值的另一种方法。 This avoids the overflow entirely.
这完全避免了溢出。 This is breaking down the sum into 2 parts -- the "carry" bits and the "non-carry" bits.
这将总和分解为两部分——“进位”位和“非进位”位。
When working with addition, the bits that are carried over to the next more significant bit are when both bits are set -- low & high
.当使用加法时,转移到下一个更重要的位的位是当两个位都被设置时——
low & high
。 Normally in addition, these bits have to be shifted left, but we're calculating the average of 2 numbers, so we would shift right in the end also.通常情况下,这些位必须左移,但我们正在计算 2 个数字的平均值,所以我们最后也会右移。 The net result: no shift here.
最终结果:这里没有变化。
The bits that aren't carried are either a 1
if the bits are different or a 0
if the bits are the same -- that's where (low ^ high)
comes from (XOR).未承载的比特要么是一个
1
,如果比特是不同的或0
,如果比特是相同的-这就是(low ^ high)
来源于(XOR)。 Normally in addition, these bits aren't shifted, but we're calculating the average of 2 numbers, so we would shift right in the end also.此外,通常情况下,这些位不会移位,但我们正在计算 2 个数字的平均值,因此我们最终也会右移。 This shift shows up as
>> 1
.这种转变显示为
>> 1
。 The &
and ^
operators don't overflow, so >>
will work just fine here. &
和^
运算符不会溢出,因此>>
在这里可以正常工作。
Example: Average of 1100 (12) and 1010 (10)示例:1100 (12) 和 1010 (10) 的平均值
1100 & 1010 = 1000
1100 ^ 1010 = 0110, 0110 >> 1 = 0011
1000 + 0011 = 1011 (11)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.