二进制位运算和状态存储

在很多系统的权限/选项设置中 很多都用到了位运算的方法来存储多种标志位。在系统设计中只要是状态只有两种状态(0,1)的都可以用二进制位来表示,如果有多个状态用多个位或者还是新加字段吧。

(1)可以节省字段。一个字段只需要一个数字 就可以标识很多种设置和信息。

(2)可以处理位置状态需求,而无需更改数据表结构,比如需求增加是否绑定微信。

  1. 案例:User用户表stat字段

    1. #二进制-标志位
      0000 0000 0000 0001 第一位是否删除
      0000 0000 0000 0010 第二位手机认证
      0000 0000 0000 0100 第三位微信认证

2. 如何用一个数字来标识这些权限位呢

以刚才的user表中stat字段为例,假如通过select stat from user where name='yubing'; 检索出来的状态值为$stat =5, 

如何检查是否微信认证呢? 看上面的对照表第三位1表示微信认证。

$stat=5;原来的状态值

$b=0b100;//第三位二进制值

$stat&$b = 5 & 0100 = 0b100 = 4 两个值相等表示状态为1,表示认证过了。

因此 检查,某个数代表的第N个权限标志位有没有置位(是1) 。同理检查是否手机认证,手机状态位为第二位

$stat&0b10==0b10 结果为0,表示没有手机认证。

3.php对应的算法
 /*
 * $stat 状态值
 * $position 对应的第几位标志位
 * return 返回标志位是否为1
 */ 
 function getStat($stat,$position){
	$t = pow(2, $position - 1);
	return ((int)$stat&$t)==$t;
 }
 /*
 * $stat 状态值
 * $position 对应的标志值
 * $val 设置标志位值1或者0
 * return 状态值
 */ 
 function setStat($stat,$position=1,$val=1){
    $t = pow(2, $position - 1);
	return $val==1? ((int)$stat | $t) : ((int)$stat & ~$t);
 }
4.如何直接修改数据库中的标志位值呢?
   比如修改用户的手机认证状态为认证 ,update user set stat=stat|2 where user='yubing'; 

修改用户的微信状态为不认证 update user set stat=stat&(~4) where user='yubing'; 同时修改状态为手机认证,微信不认证 update user set stat=stat|2&(~4) where user='yubing';

5.使用二进制位的不便之处就是需要记忆各个位表示什么状态,程序的可读性比较差。折中的解决办法,直接设置一个数组变量

$stat=['del'=>1,'mobile'=>0b10,'wx'=>4];  值为运算后的的2进制或者10进制值

猜你喜欢

转载自blog.csdn.net/robinhunan/article/details/80446128