以前寫排序演算法時有用到取index平均值的運算,通常的寫法是這樣的:
mid = lo + (hi - lo) / 2;
這樣的寫法是為了防止溢位,大家應該都清楚,記得leetcode上有一道題目專門設定了這個陷阱,相加除2的方法會導致結果錯誤。
最近在看arraylist系統原始碼時,看到了下面這種寫法:
mid = (lo + hi) >>> 1;
先複習一下移位操作:
>>> 表示無符號右移,>> 表示有符號右移,右移n位相當於除以2的n次冪。溢位的情況比較特殊,具體到求平均值的情況,兩個int型別正整數相加,即使發生溢位也至多1位,就是說符號位會變成1但不會再產生進製了,因此並不會丟失精度。這個時候我們可以把它看做無符號整數,然後使用無符號右移1位,相當於除以2,高位補0不再溢位,所以結果還是對的。但如果我們使用有符號右移,它會被看成乙個負數,最高位補1,導致結果錯誤。兩者的區別在於右移後,>>> 最高位補0,>> 正數最高位補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...