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