简体   繁体   English

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

[英]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.

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