二進制在項目中的小應用

在一個32位的計算機中,一個int型由4個字節,32個比特位組成。在日常使用中,一個int代表一個數字。在數據表中,可以代表某一事物或事件的一種狀態。但這樣未免太過單調。而且我們很難通過一個字段表示多種多種狀態,且狀態之間相互獨立。即一個狀態的改變不應該影響其他狀態。比如,某個事件有A,B,C 三個狀態。 可以發生的狀態組合有A/B/C/AB/AC/BC/ABC。

方法1:如果用一個int類型的字段代表狀態,我們可以通過 以下發送代表各種組合

    A=1
    B=2
    C=3
    AB=4
    AC=5
    BC=6
    ABC=7

  確實,上面是可以實現,但代碼編寫爲變動非常複雜,比如

   1.我要判斷是否有C狀態

   if(status ==3 || status == 5 || status ==5 || status== 7)

   2.撤銷某個狀態或者新增某個狀態會變得複雜,我們必須知道當前的狀態,然後才能進行撤銷或者新增,比如新增C狀態

   if(status ==3 || status == 5 || status ==5 || status== 7)  //已有C狀態,直接返回

   elseif(status=1){ status==xxx}  判斷現在是什麼狀態,然後設置對應的值 

   elseif(status=2) {status==yy} 

   .... 

 3. 如果這個事件新增加了狀態C,D,F 那麼複雜度會變得更恐怖。

方法2:通過多個int字段代碼各種狀態。

      A,B,C各用一個字段表示,這樣複雜度變的簡單很多。同時不管設置狀態還是撤銷狀態都會簡單很多。但是也有個問題,如果新增了C,D,F狀態就需要新增字段。並且雖然後期狀態類型的增多,需要不斷的添加爲數據表添加字段。而這種行爲是不建議的。

    1.新增字段需要鎖表,會影響服務,而且數量越多,影響時間越長

    2.空間的浪費,如果有20狀態,就需要 20個字段, 如果有N行數據,則共需要空間 20*4*N 個字節

方法3:通過bit佔位表示各種狀態

        一個int有32個比特位,那麼就可以表示32種狀態值。

        用低四位分表示 :A,B,C,D,其餘高28位用於備用
             0000  無
             0001  A
             0010  B
             0100  C
             1000  D
        

       設置狀態:
             原值status = 0
            1.觸發A: status=status|1   ->(0001)
            2.觸發B:  status=status|2  ->(0011) 
            3.觸發C: status=status|4  ->(0111) 
            4.觸發D: status=status|8  ->(1111) 
        
        判斷是否出現某種狀態 :
            A:  status & 1(0001) == 1 
            B:  status & 2(0010) == 2 
            C:  status & 4(0100) == 4
            D:  status & 8(1000) == 8          
        
        撤銷某狀態:
          A:  status &16 (1110) 
          B:  status &15 (1101)  
          C:  status & 13(1011)
          D:  status & 7(0111)     

        對於新增一個狀態, 原來的狀態不需要變化,只需要增加一個標誌位 0000 -> 00000,但對於撤銷某種狀態,增加一個標誌位,會有影響,因此撤銷標誌位,應該通過調用特定函數,不應該零散的寫在不同地方,避免增加標誌位之後,出現大量修改。

    比如調用如下代碼進行狀態撤銷:

cancelStatus(22,2); //10110=22
//status 當前狀態
//num: 撤銷第N位狀態
function cancelStatus($status,$num){
    $bit = 5; //5個標誌位
    if($num>$bit || $num<1){
        return false;
    }
    $max = pow(2,$bit)-1; //11111
    $flag = pow(2,$num-1); //00010
    $result = $max ^ $flag;  //11101
    $newstatus =  $result & $status;
    //do something
}

          撤銷某狀態:
          A:  cancelStatus(status,1)
          B:  cancelStatus(status,2) 
          C:  cancelStatus(status,3)
          D:  cancelStatus(status,4)    

     這樣做的優缺點是:

     1.編碼邏輯變的簡單

     2.狀態的增加,不需要新字段,不影響舊有邏輯,也不需要對原來的邏輯進行修改。只是需要修改cacelStatus 中的bit 尾數。做到最少修改

     3.相比增加字段表示狀態,這種方式更節省內存空間。

     4.缺點是,二進制不太讓人理解,不符合我們的常有思維
 

二進制除了上面的應用其實還有許多用處:

   1.類型文件權限的讀寫及創建的控制

   2. 2倍數的乘除法

   3. 可以通過拆分高位,低位。用來表示不同狀態或類型等。

 

如果網友有其他應用場景,可以留言,歡迎交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章