zoukankan      html  css  js  c++  java
  • 你可能不知道的按位与、或运算技巧

    背景

    最近在园子里看到了这篇文章,

    看完这篇会有意外收获:C#枚举高级战术

    https://mp.weixin.qq.com/s/yipaL6Acil-uxq_bDDgdyg

    想起了很久之前的自己的一篇总结,特地找出来

    说说概念

    在工作中遇到按位或组合权限串。一直不是特别明白。今天终于花了半个下午的时间搞明白其中的道理。

    首先每一个权限数都是2的N次方数

    如:k1=2 ; //添加

              k2=4 ; //删除

              k3=8; //修改

              ...

    如此定义功能权限数,当需要组合权限时,就需要对各个所拥有的权限数按位或了。

    如:

             purview = k2|k3; // 赋给添加和删除权限

    当需要判断在权限串中是否拥有某一权限时,就需要进行按位与。

    如:

             if((purview & k1) >0)//判断此权限串是否拥有添加权限,结果>0 则进入if语句代码块中

              {

                     ....

              }     

    说到这里肯定会有疑问了,别急我来细细讲解。

       第一,2的8位二进制值为00000010

                     4的8位二进制值为00000100

                    8的8位二进制值为00001000

    第二,当对8和4进行按位或操作后,结果为:

                     4|8 = 12

                     00000100 |00001000 = 00001100

                  为什么会是这样呢?在进行按位或操作时 00000001|00000001=00000001   ;00000001|00000000=1 ;00000000|00000000=00000000

                  也就是说除了0|0结果是0外,其它运算结果的都是1

                 所以    00000100 |00001000 = 00001100

                也就说上面的 purview = k2|k3 的二进制值结果是 purview =00000100 |00001000 =00001100了

    第三,当对8和4进行按位与操作后,结果为:

                   4&8=0

                00000100 &00001000 = 00000000

                  同样为什么会是这样呢?在进行按位与操作时 00000001&00000001=00000001   ;00000001&00000000=00000000 ;00000000&00000000=00000000

                也就是说除了1&1结果是1外,其它运算结果的都是0

                所以 00000100 &00001000 = 00000000

                上面的if((purview & k1) >0)的结果就是 00001100&00000010 =00000000 也就是(0>0)=false

               同样if((purview & k2) >0)的结果就是 00001100&00000100 =00000100=4=k2 也就是 (4>0)=true

    这样我们就理解组合权限串和判断权限的原理了,说白了就是对2N次方数的按位与和按位或。

    应用场景

    比如在做一些社交类的需求中,经常会遇到那种点赞,推荐,明天再加个置顶的,简直没完没了,总不能今天加个字段,明天再加个吧;这时候位运算就派上用用场了,每个属性一个2N次方数,枚举定义下去,这样一个字段即可解决,新来一个属性再加个枚举即可。

    代码实现

    来个核心方法

    /// <summary>
    /// 计算权限总和
    /// </summary>
    /// <param name="OldStatus">数据库现有权限总和</param>
    /// <param name="Action">取消或设置操作(0取消,1设置)</param>
    /// <param name="StatusVal">设置操作对应的状态值</param>
    /// <returns></returns>
    public static int ReturnStatusTotal(int OldStatus, int Action, int StatusVal)
    {
    int NewStatus = OldStatus;
    if (Action == 1)
    {
    //判断此权限串是否拥有相应操作,不包括时加入权限
    if ((OldStatus & StatusVal) <= 0)
    {
    NewStatus = OldStatus | StatusVal;
    }
    }
    else
    {
    //判断此权限串是否拥有相应操作,有权限时移除权限
    if ((OldStatus & StatusVal) > 0)
    {
    NewStatus = OldStatus & ~StatusVal;
    }
    }
    return NewStatus;
    }
    
     
    
     
    
    NewStatus = CommonUtilities.ReturnStatusTotal(OldStatus, objRequest.Action, (int)StatusEnum.ZhiDing);

    总结

    有时候一个不经意的小窍门,可以帮我们解决大麻烦,所以基础很重要!!!

  • 相关阅读:
    Android开发之Sqlite的使用
    ZOJ 3607 Lazier Salesgirl
    ZOJ 3769 Diablo III
    ZOJ 2856 Happy Life
    Ural 1119 Metro
    Ural 1146 Maximum Sum
    HDU 1003 Max Sum
    HDU 1160 FatMouse's Speed
    Ural 1073 Square Country
    Ural 1260 Nudnik Photographer
  • 原文地址:https://www.cnblogs.com/lyl6796910/p/14424278.html
Copyright © 2011-2022 走看看