位移操作和求平均值溢位

2022-04-22 10:09:51 字數 970 閱讀 8363

以前寫排序演算法時有用到取index平均值的運算,通常的寫法是這樣的:

mid = lo + (hi - lo) / 2;
這樣的寫法是為了防止溢位,大家應該都清楚,記得leetcode上有一道題目專門設定了這個陷阱,相加除2的方法會導致結果錯誤。

最近在看arraylist系統原始碼時,看到了下面這種寫法:

mid = (lo + hi) >>> 1;
先複習一下移位操作:

>>> 表示無符號右移,>> 表示有符號右移,右移n位相當於除以2的n次冪。

兩者的區別在於右移後,>>> 最高位補0,>> 正數最高位補0負數補1。所以對於正數來講,兩者沒有區別,但對於負數應該使用後者。

溢位的情況比較特殊,具體到求平均值的情況,兩個int型別正整數相加,即使發生溢位也至多1位,就是說符號位會變成1但不會再產生進製了,因此並不會丟失精度。這個時候我們可以把它看做無符號整數,然後使用無符號右移1位,相當於除以2,高位補0不再溢位,所以結果還是對的。但如果我們使用有符號右移,它會被看成乙個負數,最高位補1,導致結果錯誤。

做一下測試:

int hi = integer.max_value, lo = integer.max_value - 2;

system.out.println((hi + lo) / 2);

system.out.println((hi - lo) / 2 + lo);

system.out.println((hi + lo) >> 1);

system.out.println((hi + lo) >>> 1);

輸出結果:

-2

2147483646

-22147483646

結果符合預期,所以index取平均值時,使用第二和第四種方式可以避免溢位。

java 求int平均值防止溢位

start end start 2int mid start end 1它通過移位實現了除以 2,但。這樣難道不會導致溢位嗎?首先大家可以補一下 補碼 的知識。其實問題的關鍵就是這裡了 我們知道還有一種右移是 區別在於 為有符號右移,右移以後最高位保持原來的最高位。而 這個右移的話最高位補 0。所以...

hive UDAF求平均值

最近做資料遷移專案,把聚合部分從kettle遷移到hadoop集群上,需要寫很多聚合指令碼 在論壇是看到alipay同事寫過類似cube的udaf,拿過來執行下報錯,有幾個地方沒看多,而且沒有注釋,只好從基礎開始看,自己搞乙個,之前寫過udf所以入手還是聽快的 準備 1 實現自己的udaf需要整合u...

spark 求平均值

val rdd sc.makerdd list a 1 a 2 a 3 b 1 b 2 b 3 b 4 a 4 2 rdd.combinebykey x x,1 x int,int y int x.1 y,x.2 1 x int int y int int x.1 y.1,x.2 y.2 mapva...