在一個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. 可以通過拆分高位,低位。用來表示不同狀態或類型等。
如果網友有其他應用場景,可以留言,歡迎交流。