二进制在项目中的小应用

在一个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. 可以通过拆分高位,低位。用来表示不同状态或类型等。

 

如果网友有其他应用场景,可以留言,欢迎交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值