php 位运算与权限,PHP中的二进制位运算和权限存储
在很多系統(tǒng)的權(quán)限/選項(xiàng)設(shè)置中 很多都用到了位運(yùn)算的方法來存儲(chǔ)多種標(biāo)志位。這樣可以節(jié)省字段。一個(gè)字段只需要一個(gè)數(shù)字 就可以標(biāo)識(shí)很多種設(shè)置和信息。
舉例 dicuz的帖子表的status字段,官方預(yù)留了16個(gè)標(biāo)志位(0x0000 – 0xFFFF) 即216
目前規(guī)劃使用了只有8個(gè)標(biāo)志位,如下
0000 0000 0000 0001 是否緩存帖子位置信息
0000 0000 0000 0010 是否回帖只對(duì)管理人員和發(fā)帖者可見
0000 0000 0000 0100 是否搶樓貼
0000 0000 0000 1000 是否倒序查看回帖
0000 0000 0001 0000 是否存在主題圖章標(biāo)志位
0000 0000 0010 0000 回復(fù)是否通知作者
0000 0000 0100 0000 是否推送到QQ空間
0000 0000 1000 0000 是否推送到騰訊微博
這8種狀態(tài)可以使用一個(gè)數(shù)字來同時(shí)表示,節(jié)省了字段
那么這種東西的原理是什么呢
這個(gè)我們可以復(fù)習(xí)一下的位運(yùn)算單算法
例子
名稱
結(jié)果
$a & $b
And(按位與)
將把 $a 和 $b 中都為 1 的位設(shè)為 1。
$a | $b
Or(按位或)
將把 $a 或者 $b 中為 1 的位設(shè)為 1。
$a ^ $b
Xor(按位異或)
將把 $a 和 $b 中不同的位設(shè)為 1。
~ $a
Not(按位非)
將 $a 中為 0 的位設(shè)為 1,反之亦然。
$a << $b
Shift left(左移)
將 $a 中的位向左移動(dòng) $b 次(每一次移動(dòng)都表示“乘以 2”)。
$a >> $b
Shift right(右移)
將 $a 中的位向右移動(dòng) $b 次(每一次移動(dòng)都表示“除以 2”)。
比如
與運(yùn)算
14 = 0b1110
11 = 0b1011
那么 14 & 11? = 0b1110 & 0b1011 = 0b1010 = 10
或運(yùn)算
還是上面那個(gè)例子
14 | 11 = 0b1110 | 0b1011 = 0b1111 = 15
異或運(yùn)算
14 ^ 11 = 0b1110 ^ 0b1011 = 0b0101 = 5
非運(yùn)算
非運(yùn)算比較特殊 涉及到符號(hào) 這里要說一下補(bǔ)碼 反碼 原碼的概念
1.二進(jìn)制最高是符號(hào)位? 0是正數(shù)? 1表示負(fù)數(shù)
2.正數(shù)的 原碼 反碼? 補(bǔ)碼 都一樣(我上面沒有單獨(dú)算補(bǔ)碼的原因 ,正數(shù)補(bǔ)碼和反碼一樣)
3.用二進(jìn)制表示一個(gè)數(shù)? 這個(gè)碼 就是原碼 比如 14的原碼就是 1110
4.負(fù)數(shù)的反碼 等于? 他符號(hào)位不變 其他取反,而負(fù)數(shù)的補(bǔ)碼等于他的反碼+1
5.計(jì)算機(jī)運(yùn)算的時(shí)候 全都是以補(bǔ)碼的形式來運(yùn)算的 不管正負(fù)數(shù)
那么
1 是正數(shù),那么他的原碼 0001 = 反碼 = 補(bǔ)碼 = 0001 =>取反 后補(bǔ)碼1110 <=反碼 1101<=原碼1010
那么這個(gè)符號(hào)位是1就是負(fù)數(shù) 也就是010代表的負(fù)數(shù)就是-2 也就是 ~1 = -2
左右位移運(yùn)算
1<< 2
1的補(bǔ)碼??? 00000001
移動(dòng)2位??? 00000100
正數(shù)的反碼 補(bǔ)碼? 原碼 都一樣 所以 是個(gè)4
負(fù)數(shù)的計(jì)算過程相同 不再贅述 左移也類似 4>>2? 就是1
其實(shí)可以理解為右移在十進(jìn)制的表現(xiàn)上就是乘以2 左移 在十進(jìn)制的表現(xiàn)上就是除以2
那么回到本文正題 如何用一個(gè)數(shù)字來標(biāo)識(shí)這些權(quán)限位呢?
以剛才discuz的帖子表達(dá)status字段為例,檢查帖子回復(fù)是否通知作者 就看二進(jìn)制上第六位是否是置位為1 那么怎么檢查呢?就是用上面我們提到的與運(yùn)算。
與運(yùn)算是將把 $a 和 $b 中都為 1 的位設(shè)為 1。那么假設(shè)
$a=36=0b 0010 0100
$b=0b 0010 0000
$a&$b = 0b 0010 0100 & 0b 0010 0000 = 0b 0010 0000 = 32 = 26-1?= 25
因此 檢查,某個(gè)數(shù)代表的第N個(gè)權(quán)限標(biāo)志位有沒有置位(是1) 只要選擇該數(shù)與僅該標(biāo)志位置位的操作數(shù)2N-1進(jìn)行與運(yùn)算即可,相反要計(jì)算某個(gè)標(biāo)志位被置位的數(shù)字 只要選擇合適的操作數(shù)進(jìn)行或運(yùn)算即可。我們可以看discuz對(duì)此的實(shí)現(xiàn):
function getstatus($status, $position) { $t = $status & pow(2, $position – 1) ? 1 : 0; return $t;}function setstatus($position, $value, $baseon = null) { $t = pow(2,$position – 1); if($value) { $t = $baseon | $t; } elseif ($baseon !== null) { $t = $baseon & ~$t; } else { $t = ~$t; } return $t & 0xFFFF;}
注意 寫這段代碼的人顯然受到了C的影響 其實(shí) $a & ~$b 和 $a ^ $b 是等效的 只不過 ^是PHP的寫法 另外 pow(2, $position – 1)換成 1 << ($position -1) 其實(shí)更好理解。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的php 位运算与权限,PHP中的二进制位运算和权限存储的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (视频+图文)机器学习入门系列-第4章
- 下一篇: php上传图片管理系统,php 登录操作