[underscore源碼學習]——`>>` 運算符和二分查找

這是一篇記錄學習 underscore v0.0.5 的fragment,以爲有點意思,和你們分享一下。數組

先看_.sortedIndex的源碼,它用來肯定 obj 在 array中的位置(array升序):ide

_.sortedIndex = function(array, obj, iterator) {
    iterator = iterator || _.identity;
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >> 1;
      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    }
    return low;
  };

  _.identity = function(value) {return value};

代碼雖短卻兩個我不經常使用的姿式:>> 運算符和二分查找。學習


右移運算符 >>

右移運算符的計算規則以下操作系統

int a = 8; int b = a >> 1; // b ?
先將 8 轉化爲二進制數,(在 C 中,32位操做系統下int 類型佔2個字節,即16bit)
0000 0000 0000 1000
總體右移 1 位,高位不足添 0
0000 0000 0000 0100
再將新的二進制數轉化爲十進制獲得 b = 4;code

那麼,代碼 var mid = (low + high) >> 1 mid 變量取值是多少呢?由於好(dou)奇(bi),我做了一點嘗試:underscore

0 >> 1  // 0
1 >> 1  // 0
2 >> 1  // 1
3 >> 1  // 1
4 >> 1  // 2
5 >> 1  // 2
...
10 >> 1 // 5
11 >> 1 // 5
12 >> 1 // 6
...

由概括法可得 a >> 1 === parseInt(a / 2)。這點相信眼尖的同窗早就看出來了。源碼

二分查找

既然咱們已經知曉mid >> 1 === parseInt((low + high) / 2),咱們再來回顧下代碼片斷:it

while (low < high) {
  var mid = (low + high) >> 1;                                        // (1)
  iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; // (2)
}

(1)咱們已經知曉,mid 取得了一箇中間數值,在(2)中是一個三元運算符,解釋起來,就是用一個有序數組 array 的中間數和目標數進行比較,則若是中間數比目標數小,就只須要比較中間數右側的值,反之亦然。而後繼續循環...io

等價於下面的代碼,由此差距立顯:function

while (low < high) {
  var mid = (low + high) >> 1;                                        
  var a = iterator(array[mid]);
  var b = iterator(obj)
  if(a == b) {
    return mid;
  } else if(a < b) {
    low = mid + 1;
  } else {
    high = mid
  } 
}

題外話

內容照理說已經講完了,但對於 >>運算符我仍是有些疑慮。既然有a >> 1 === parseInt(a / 2) 那麼能否假設 a >> 2 === parseInt(a / (2*2))呢?

0 >> 2  // 0
3 >> 2  // 0

4 >> 2  // 1
7 >> 2  // 1

8 >> 2  // 2
11 >> 2 // 2

12 >> 2 // 3

繼而a >> 3 === parseInt(a / (2*2*2)),可得a >> n === parseInt(a / (X)) X 爲 2 的 n 次方。

左移運算符 <<

與右移運算符相對的叫左移運算符,記爲 <<,相信它也不是吃乾飯的。

有了前面的鋪墊,我這裏一步到位,假設有a << n === parseInt(a * (X)) X 爲 2 的 n 次方。簡單驗證下:

1 << 1 // 1*2 = 2
2 << 1 // 2*2 = 4
3 << 2 // 3 * (2*2) = 12
5 << 4 // 5 * (2*2*2*2) = 80
...

最後的最後,因爲水平有限(你們看出來了,忍住不要笑:-D),文章內容連蒙帶猜,沒有通過特別嚴謹的證實,歡迎拍磚!!!

相關文章
相關標籤/搜索