[英]Java, will (low + high) >> 1 overflow?
我知道>>
用於已簽名,而>>>
用於未簽名
沒有回答我的問題的類似問題:
根據第二個鏈接,他們為什么得出結論: avg = (low & high) + ((low ^ high) >> 1);
會避免溢出嗎?
為什么他們不能直接使用它 : (low + high) >> 1
?
(這是用於java中的二進制搜索)
是的, (low + high) >> 1
如果總和足夠高,可能會溢出。 如您所知, >>>
用於無符號,因此它始終會在最重要的一側移動0
。 事實證明,這在它確實溢出時非常重要。
即使有溢出,使用(low + high)
的技巧是仍然保留信息。 如果它確實溢出,最大可能的數學總和仍然是Integer.MAX_VALUE * 2
,如果 Java 有一個 unsigned int
,它仍然可以表示為 unsigned int
。 但是,再除以2,當使用無符號向右移位運算,我們可以把之作為一個unsigned int, >>>
。 當右移1
,這讓我們將總和視為 unsigned int
,“不溢出” int
。
如果總和溢出,在此處使用>>
將不起作用,因為它將溢出為負數,而>>
將移入1
,從而使值保持為負。 這會導致不正確的平均值計算(2 個正數的總和溢出將導致負平均值)。
無論您使用的是>>>
還是>>
,都有可能發生溢出。 所以兩者都可以溢出。 但只有>>>
才能很好地處理這個案子,正確地“不溢出”總和。
訣竅
avg = (low & high) + ((low ^ high) >> 1);
是在總和可能溢出時計算平均值的另一種方法。 這完全避免了溢出。 這將總和分解為兩部分——“進位”位和“非進位”位。
當使用加法時,轉移到下一個更重要的位的位是當兩個位都被設置時—— low & high
。 通常情況下,這些位必須左移,但我們正在計算 2 個數字的平均值,所以我們最后也會右移。 最終結果:這里沒有變化。
未承載的比特要么是一個1
,如果比特是不同的或0
,如果比特是相同的-這就是(low ^ high)
來源於(XOR)。 此外,通常情況下,這些位不會移位,但我們正在計算 2 個數字的平均值,因此我們最終也會右移。 這種轉變顯示為>> 1
。 &
和^
運算符不會溢出,因此>>
在這里可以正常工作。
示例: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.