美文网首页
位运算及其应用场景

位运算及其应用场景

作者: 蓝汀华韶 | 来源:发表于2020-11-06 10:02 被阅读0次
    概念理解
    • 按位与 & :全1为1,有0为0

    假设 1:true,0:false,联想Java中的&&运算符,只有两个都为true才为true,其他均为false
    &举例:
    0000 0011
    0000 1010
    ==============
    0000 0010

    • 按位或 | :有1为1,全0为0

    假设 1:true,0:false,联想Java中的||运算符,只有有一个为为true就为true,全为false才为false
    | 举例:
    0000 0011
    0000 1010
    ==============
    0000 1011

    • 按位异或 ^ :不同为1,相同为0

    假设1为男性,0为女性,异性相吸修成正果则为1,同性相斥孤独终老为0
    ^ 举例:
    0000 0011
    0000 1010
    ==============
    0000 1001

    按位非:~ :按位取反,1为0,0为1

    ~ 举例:
    0000 0011 ~
    ==============
    1111 1100

    • 有符号左移 << :各二进位全部左移若干位,高位丢弃,低位补0
      若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2
      a = a << 2 = a + 2的2次方

    举例:
    0000 1101 =
    << 2位
    ====================
    0011 0100

    • 有符号右移 >> :将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
      操作数每右移一位,相当于该数除以2。
      a = a >> 2 相当于 a除以2的2次方

    举例:
    0000 1101 =
    >> 2位
    ====================
    0000 0011 = 3

    • 无符号右移 >>> :将一个数的各二进制位全部右移若干位,高位补0
    // 1010
    System.out.println("10 = " + Integer.toBinaryString(10));
    
    // 0110
    System.out.println("6 = " + Integer.toBinaryString(6));
    
    // 按位与: 1&1=1 1&0 = 0 0&1=0 0&0=0
    // 0010
    System.out.println("10 & 6 = " + Integer.toBinaryString(10 & 6));
    
    // 按位或:1&1=1 1&0=1 0&1=1 0&0=0
    // 1110
    System.out.println("10 | 6 = " + Integer.toBinaryString(10 | 6));
    
    // 按为异或:1&1=0 1&0=1 0&1=1 0&0=0
    // 1100
    System.out.println("10 ^ 6 = " + Integer.toBinaryString(10 ^ 6));
    
    
    // 左移
    int a = 10;
    // 1010 <<2 = 0010 1000
    // 40 = 10 * 2 ^ 2
    System.out.println("a << 2 = " + (a << 2));
    // 0010 1000
    System.out.println("a << 2 = " + Integer.toBinaryString((a << 2)));
    
    // 右移
    int b = 101;
    // 0110 0101
    System.out.println("b = " + Integer.toBinaryString(101));
    // 101 / 2^2 = 25
    System.out.println("b >> 2 = " + (b >> 2));
    // 0001 1001
    System.out.println("b >> 2 = " + Integer.toBinaryString((b >> 2)));
    
    应用场景

    1、取模

    当一个数a除以 2的n次方求余数时,(a / 2^n)等价于 a & (2^n - 1)
    原理:某个数A,对 2^n 取模,则余数最大值为 2^n-1 ,当按位与上 2^n-1 时,高位的都被舍弃,只留下了2^n-1中满足条件的余数

    /**
     * 如果取模的分母是2的N次方,则等价于 &上2的N次方-1
     * b % 4 = b & (2 ^2 - 1)
     * b = 101
     *   0110 0101
     * & 0000 0011
     * ---------------
     *   0000 0001
     *
     *   b = 111 % 16 = 15
     *
     *   0110 1111
     *   0000 1111
     *   ------------
     *   0000 1111
     *
     */
    // 1
    int b = 101;
    System.out.println("b % 4 = " + (b % 4) + " = " + (b & (4 - 1)));
    b = 111;
    // 15
    System.out.println("b % 16 = " + (b % 16) + " = " + (b & (16 - 1)));
    

    2、保存操作状态或商品属性开关

    权限控制,有增删改查四种权限,传统意义上会在新增四个属性分别对应四种权限,如果有再新增权限的话,又要新增属性
    在这种情况下,可以使用位,一个int类型有32位,理论上可以存储32个属性、状态

    /**
     * 权限操作类
     */
    public class Permissions {
    
        /**
         * 二进制第1位是否允许查询,0表示否,1表示是
         * 1 << 0 = 0001  = 1
         */
        public static final int ALLOW_SELECT = 1 << 0;
    
        /**
         * 二进制第2位是否允许新增,0表示否,1表示是
         * 1 << 1 = 0010  = 2
         */
        public static final int ALLOW_INSERT = 1 << 1;
    
        /**
         * 二进制第3位是否允许修改,0表示否,1表示是
         * 1 << 2 = 0100 = 4
         */
        public static final int ALLOW_UPDATE = 1 << 2;
    
        /**
         * 二进制第4位是否允许删除,0表示否,1表示是
         * 1 << 3 = 1000 = 8
         */
        public static final int ALLOW_DELETE = 1 << 3;
    
    
        /**
         * 目前所拥有的权限状态
         */
        private int flag;
    
        public int getFlag() {
            return flag;
        }
    
        public void setFlag(int flag) {
            this.flag = flag;
        }
    
        /**
         * 新增1个或者多个权限
         * 按位或,有1为1,全0为0,按位或后有1的位置全都有了权限
         */
        public void addPermission(int flag) {
            this.flag = this.flag | flag;
        }
    
        /**
         * 删除1个或多个权限
         * 先按位取反,这样不需要删除的位置为1,删除的位置为0,在按位与,将对于为0的位置置0
         *
         */
        public void removePermission(int flag) {
            this.flag = this.flag & ~flag;
        }
    
        /**
         * 是否有某个操作的权限
         * 先按位与后如果操作位对应的是1,则操作位继续为1,否则全为0,得到的结果要么为flag,要么全为0
         */
        public boolean hasPermission(int flag) {
            return (this.flag & flag) == flag;
        }
    
        public boolean hasNotPermission(int flag) {
            return (this.flag & flag) == 0;
        }
    
        /**
         * flag : 0, insert : false
         * flag : 0, delete : false
         * flag : 0, update : false
         * flag : 0, select : false
         * 添加查询权限
         * flag : 1, insert : false
         * flag : 1, delete : false
         * flag : 1, update : false
         * flag : 1, select : true
         * 添加修改权限
         * flag : 5, insert : false
         * flag : 5, delete : false
         * flag : 5, update : true
         * flag : 5, select : true
         * 添加删除权限
         * flag : 13, insert : false
         * flag : 13, delete : true
         * flag : 13, update : true
         * flag : 13, select : true
         * 添加插入权限
         * flag : 15, insert : true
         * flag : 15, delete : true
         * flag : 15, update : true
         * flag : 15, select : true
         * 去掉查询权限
         * flag : 14, insert : true
         * flag : 14, delete : true
         * flag : 14, update : true
         * flag : 14, select : false
         * 去掉修改权限
         * flag : 10, insert : true
         * flag : 10, delete : true
         * flag : 10, update : false
         * flag : 10, select : false
         * 去掉删除权限
         * flag : 2, insert : true
         * flag : 2, delete : false
         * flag : 2, update : false
         * flag : 2, select : false
         * 去掉插入权限
         * flag : 0, insert : false
         * flag : 0, delete : false
         * flag : 0, update : false
         * flag : 0, select : false
         */
        public static void main(String[] args) {
            // 默认没有任何权限
            int flag = 0;
            Permissions permissions = new Permissions();
            permissions.setFlag(flag);
            permissions.print(permissions);
            // 添加查询权限
            System.out.println("添加查询权限");
            permissions.addPermission(Permissions.ALLOW_SELECT);
            permissions.print(permissions);
            // 添加修改权限
            System.out.println("添加修改权限");
            permissions.addPermission(Permissions.ALLOW_UPDATE);
            permissions.print(permissions);
            // 添加删除权限
            System.out.println("添加删除权限");
            permissions.addPermission(Permissions.ALLOW_DELETE);
            permissions.print(permissions);
            // 添加插入权限
            System.out.println("添加插入权限");
            permissions.addPermission(Permissions.ALLOW_INSERT);
            permissions.print(permissions);
    
            // 去掉查询权限
            System.out.println("去掉查询权限");
            permissions.removePermission(Permissions.ALLOW_SELECT);
            permissions.print(permissions);
    
            // 去掉修改权限
            System.out.println("去掉修改权限");
            permissions.removePermission(Permissions.ALLOW_UPDATE);
            permissions.print(permissions);
    
            // 去掉删除权限
            System.out.println("去掉删除权限");
            permissions.removePermission(Permissions.ALLOW_DELETE);
            permissions.print(permissions);
    
            // 去掉插入权限
            System.out.println("去掉插入权限");
            permissions.removePermission(Permissions.ALLOW_INSERT);
            permissions.print(permissions);
        }
    
        private void print(Permissions permissions) {
            System.out.println("flag : " + permissions.getFlag() + ", insert : " + permissions.hasPermission(Permissions.ALLOW_INSERT));
            System.out.println("flag : " + permissions.getFlag() + ", delete : " + permissions.hasPermission(Permissions.ALLOW_DELETE));
            System.out.println("flag : " + permissions.getFlag() + ", update : " + permissions.hasPermission(Permissions.ALLOW_UPDATE));
            System.out.println("flag : " + permissions.getFlag() + ", select : " + permissions.hasPermission(Permissions.ALLOW_SELECT));
        }
    
    }
    

    相关文章

      网友评论

          本文标题:位运算及其应用场景

          本文链接:https://www.haomeiwen.com/subject/yeqivktx.html