• 聊聊位运算吧


       什么是位运算

                先说说 什么是位运算,程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。说白的位运算就是将整数在内存中的二进制的进行运算。

       c#对应的位运算

    运算符号
    意义
    运算对象类型
    运算结果类型
    对象数
    实例
    ~
    位逻辑非运算
    整型,字符型
    整型
    1
    ~a
    &
    位逻辑与运算
    2
    a & b
    |
    位逻辑或运算
    2
    a | b
    ^
    位逻辑异或运算
    2
    a ^ b
    << 
    位左移运算
    2
    a<<4
    >> 
    位右移运算
    2
    a>>2

         

      位运算的使用场景

        

    1. ~ 位求反

    运算符规则是:将运算符后二进制数反转,0变1,1变 0,所以对一个数取反偶数次结果是它本身。

    例如:

     
    0000 0000 0000 0000 0000 0000 0000 0011 -> 3
    1111 1111 1111 1111 1111 1111 1111 1100 -> ~ 3 = -4

    常用场景:

    求相反数: ~a + 1


    2. << 左移

    运算符规则是:各二进位全部左移若干位,高位丢弃,低位补0。

    例如:6 << 2 = 24

     
     
    0000 0000 0000 0000 0000 0000 0000 0110 -> 6
    0000 0000 0000 0000 0000 0000 0001 1000 -> 6 << 2 = 24

    我们将6的二进位向左移动两位,低位补上两个0,高位丢弃,得出来的结果就是24。

    常用场景:

    左移常被用来做 * (2 ^ n)的运算,因为直接基于二进制运算,所以左移效率比 * (2 ^ n)高。


    3. >> 右移

    运算符规则是:各二进位全部右移若干位,正数高位补0,负数高位补1,低位丢弃。

    例如: 12 >> 2 = 3

     
     
    0000 0000 0000 0000 0000 0000 0000 1100     -> 12
    0000 0000 0000 0000 0000 0000 0000 0011     -> 12 >> 2 = 3

    因为12是正数,右移过程中高位补上两个0,低位丢弃,得出来的结果就是3。
    例如:-12 >> 2 = -3

     
     
    1111 1111 1111 1111 1111 1111 1111 0100    -> -12
    1111 1111 1111 1111 1111 1111 1111 1101    -> -12 >> 2 = -3

    因为-12是负数,右移过程中高位补上两个1,低位丢弃,得出来的结果就是-3。

    常用场景:

    右移常被用来做 / (2 ^ n)的运算,因为直接基于二进制运算,所以右移效率比 / (2 ^ n)高。


    4. >>> 无符号右移

    运算符规则是:各二进位全部右移若干位,高位补0,低位丢弃。

    例如: 12 >>> 2 = 3

     
     
    0000 0000 0000 0000 0000 0000 0000 1100     -> 12
    0000 0000 0000 0000 0000 0000 0000 0011     -> 12 >>> 2 = 3

    我们将12的二进位向右移动两位,高位补上两个0,低位丢弃,得出来的结果就是24。
    例如:-12 >>> 2 = 1073741821

     
     
    1111 1111 1111 1111 1111 1111 1111 0100    -> -12
    0011 1111 1111 1111 1111 1111 1111 1101    -> -12 >> 2 = 1073741821

    我们将-12的二进位向右移动两位,高位补上两个0,低位丢弃,得出来的结果就是1073741821。

    5. & 位与
    运算符规则是:运算符两边有0,结果就为0 ,只有当两边同时为1是,结果才为1。

    如下:

     0 & 0 = 0;     0 & 1 = 0;     1 & 0 = 0;       1 & 1= 1;

    例如:3&5  

     
     
     
    0000 0000 0000 0000 0000 0000 0000 0011 -> 3
    0000 0000 0000 0000 0000 0000 0000 0101 -> 5
    0000 0000 0000 0000 0000 0000 0000 0001 -> 3 & 5 = 1

    位与运算的特殊用途:

    1.清零(将一个单元与0进行位与运算结果为零)
    2.取一个数指定位(例如取num=1010 1101的低四位 则将num&0xF得到0000 1101)。
    3.判断奇偶性:用if ((a & 1) == 0) 代替 if (a % 2 == 0)来判断a是不是偶数。


    6. | 位或
    运算规则就是 运算符两边有1,结果就为1 ,只有当两边同时为0是,结果才为0。

    如下:

     
    0 | 0 = 0;  0 | 1 = 1;  1 | 0 = 1;   1 | 1 = 1 ;

    例如:3|5 

     
     
     
    0000 0000 0000 0000 0000 0000 0000 0011 -> 3
    0000 0000 0000 0000 0000 0000 0000 0101 -> 5
    0000 0000 0000 0000 0000 0000 0000 0111 -> 3 | 5 = 7

    另,负数按补码形式参加按位或运算。

    使用场景:

    下面这个方法是摘自HashMap类,这个算法来修改用户使用构造器传进来的size的,这个算法是使用移位和或结合来实现的,性能上比循环判断要好。

     
    public static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

    7. ^ 位异或
    运算规则是:当运算符两边相同位置都是相同,结果返回0,不相同时返回1。

    例如:3 ^ 5 = 1

     
    0000 0000 0000 0000 0000 0000 0000 0011 -> 3
    0000 0000 0000 0000 0000 0000 0000 0101 -> 5
    0000 0000 0000 0000 0000 0000 0000 0110 -> 3 ^ 5 = 6

    通常我们交换两个数会使用一个临时变量来帮忙:

    int t = a;
    a = b;
    b = t;
     
    使用 ^ 位运算符(装逼必备)
    a ^= b;
    b ^= a;
    a ^= b;
     
  • 相关阅读:
    Oracle与MySQL的转化差异
    iOS 创建静态库文件时去掉当中的Symbols
    hdu4336 Card Collector 状态压缩dp
    随机森林——Random Forests
    OpenCV码源笔记——Decision Tree决策树
    海明距离hamming distance
    学习OpenCV——Surf简化版
    学习OpenCV——用OpenCv画漫画
    学习OpenCV——ORB简化版&Location加速版
    学习OpenCV——hand tracking手势跟踪
  • 原文地址:https://www.cnblogs.com/YorkQi/p/14439834.html
Copyright © 2020-2023  润新知