zoukankan      html  css  js  c++  java
  • 位运算总结 (左移、右移、按位与、按位或、按位非、按位异或)

    刷题的时候碰见了一些位运算,有印象但是对它们的算法实际用处不了解,于是就再次回顾一下其表现特征,归纳一下了解到的知识点~

    参考:

    位运算(按位与、按位或、异或)

    按位异或运算 (正数异或负数) 、按位非(~)

    15种位运算的妙用,你都知道吗?

    规则:

    正数:反码、原码、补码相同,符号位为0

    负数:反码,符号位为1,数值位按位取反

    补码,反码+1

    已知负数补码求原码:符号位不变,数值位减1再取反; 或者,符号位不变,数值位取反后再加1

    所有参与运算的都是以补码形式进行的 结果也是补码 因此也需要将补码转换成为原码的形式存在
    左移 <<
    • 左移的特征:用来倍增(乘2^n,n为移动的数值)。
    NSLog(@"1左移-->%d",1<<1);//0001 -->2
    NSLog(@"2左移-->%d",2<<1);//0010 -->4
    NSLog(@"3左移-->%d",3<<1);//0011 -->6
    NSLog(@"4左移-->%d",4<<1);//0100 -->8
    NSLog(@"5左移-->%d",5<<1);//0101 -->10
    NSLog(@"6左移-->%d",6<<1);//0110 -->12
    NSLog(@"7左移-->%d",7<<1);//0111 -->14
    NSLog(@"8左移-->%d",8<<1);//1000 -->16
    
    右移 >>
    • 右移的特征:用来整除(除2^n,n为移动的数值)并舍去余数。
    NSLog(@"1右移-->%d",1>>1);//0001 -->0
    NSLog(@"2右移-->%d",2>>1);//0010 -->1
    NSLog(@"3右移-->%d",3>>1);//0011 -->1
    NSLog(@"4右移-->%d",4>>1);//0100 -->2
    NSLog(@"5右移-->%d",5>>1);//0101 -->2
    NSLog(@"6右移-->%d",6>>1);//0110 -->3
    NSLog(@"7右移-->%d",7>>1);//0111 -->3
    NSLog(@"8右移-->%d",8>>1);//1000 -->4
    
    按位与 &
    • 与的特征:只有两个数的二进制同时为1,结果才为1,否则为0
    • 与1运算,可以判断奇偶性。 A&1 = 0 (偶数). A&1 = 1 (奇数)
    NSLog(@"按位与-->%d",0&0);//0000 & 0000 0
    NSLog(@"按位与-->%d",0&1);//0000 & 0001 0
    NSLog(@"按位与-->%d",1&0);//0001 & 0000 0
    NSLog(@"按位与-->%d",1&1);//0001 & 0001 1
    NSLog(@"按位与-->%d",2&2);//0010 & 0010 2
    NSLog(@"按位与-->%d",4&4);//0100 & 0100 4
    NSLog(@"按位与-->%d",-2&2);// 2
    NSLog(@"按位与-->%d",-4&4);// 4
    NSLog(@"-->%d",-7&7);//1
    
    //判断奇偶性
    NSLog(@"按位与-->%d",0&1);//0
    NSLog(@"按位与-->%d",1&1);//1
    NSLog(@"按位与-->%d",2&1);//0
    NSLog(@"按位与-->%d",3&1);//1
    /*
      -2 和 2为例:
      1000 0000 0000 0010 -2原码
      1111 1111 1111 1101 -2反码
      1111 1111 1111 1110 -2补码
      0000 0000 0000 0010 2 结果为2
    */
    
    按位或 |
    • 或的特征:数值位只要两个数中的一个为1,结果就为1。
    NSLog(@"按位或-->%d",0|0);//0000 & 0000 0
    NSLog(@"按位或-->%d",0|1);//0000 & 0001 1
    NSLog(@"按位或-->%d",1|0);//0001 & 0000 1
    NSLog(@"按位或-->%d",1|1);//0001 & 0001 1
    NSLog(@"按位或-->%d",2|2);//0010 & 0010 2
    NSLog(@"按位或-->%d",4|4);//0100 & 0100 4
    NSLog(@"按位或-->%d",-2|2);// -2
    NSLog(@"按位或-->%d",-4|4);// -4
    /*
     -2 和 2
     1000 0000 0000 0010 原码
     1111 1111 1111 1101 反码
     1111 1111 1111 1110 补码
     0000 0000 0000 0010 2补码
     1111 1111 1111 1110 结果为补码,如果是负数需要转成原码
     1111 1111 0000 0001 符号位不变,取反
     1111 1111 0000 0010 +1 为-2
    */
    
    按位非 ~
    • 非的特征:按位取反 (最终表现为:先加1后取反,按照这个特性,数学用途可以归纳为求相反数:~A + 1)
    NSLog(@"0按位非-->%d",~0);//0000 -1
    NSLog(@"1按位非-->%d",~1);//0000 -2
    NSLog(@"2按位非-->%d",~2);//0010 -3
    NSLog(@"3按位非-->%d",~3);//0010 -4
    NSLog(@"4按位非-->%d",~4);//0100 -5
    NSLog(@"-2按位非-->%d",~-2);//  1
    NSLog(@"-4按位非-->%d",~-4);//  3
            
    /*
     0000 0000 0000 0000 0
     1111 1111 1111 1111 按位取反
     1111 1111 0000 0001 负数,符号位不变,取反+1 结果为-1
    
     1111 1111 0000 0010 -2
     1111 1111 1111 1110 -2补码
     0000 0000 0000 0001 取反,正数,结果为1
    
     1111 1111 0000 0100 -4
     1111 1111 1111 1100 -4补码(取反+1)
     0000 0000 0000 0011 3
    
     */
    
    按位异或 ^
    • 异或的特征:参加运算的两个数,如果两个相应位为"异"(值不同),则该位结果为1,否则为0。
    • 任意数和自身异或结果为0,用于置0
    • 可以判断两个数是否相等,if((A^B ) == 0)
    • 0和任意数异或结果还是其本身。
    • 交换两个数,a = a^b;b = b^a;a = a^b;
    NSLog(@"按位异或-->%d",0^0);//0
    NSLog(@"按位异或-->%d",0^1);//1
    NSLog(@"按位异或-->%d",1^2);//3
    NSLog(@"按位异或-->%d",-2^1);//-1
    NSLog(@"按位异或-->%d",-3^-2);//3
    /*
     0^1
     0000 0000 0000 0000 0
     0000 0000 0000 0001 1
     0000 0000 0000 0001 1
     1^2
     0000 0000 0000 0001 1
     0000 0000 0000 0010 2
     0000 0000 0000 0011 3
     -2^1
     1111 1111 0000 0010 -2 原码
     1111 1111 1111 1110 -2补码(取反+1)
     0000 0000 0000 0001 1
     1111 1111 1111 1111 符号位为负数,求其原码
     1111 1111 0000 0001 -1(取反+1)
     -3^-2
     1111 1111 0000 0011 -3原码
     1111 1111 1111 1101 -3补码
     1111 1111 1111 1110 -2补码
     0000 0000 0000 0011 3
     */
    

    位运算总结:

    1. 整数的平均值

    对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:

    int average(int x, int y)   //返回X,Y 的平均值
    {   
         return (x&y)+((x^y)>>1);
    }
    

    2. 判断一个整数是不是2的幂,对于一个数 x >= 0

    boolean power2(int x)
    {
        return ((x&(x-1))==0)&&(x!=0);
    }
    

    3. 用位运算符交换两个整数

    void swap(int x , int y)
    {
        x ^= y;
        y ^= x;
        x ^= y;
    }
    

    4. 计算绝对值

    int abs( int x )
    {
      int y ;
      y = x >> 31 ;
      return (x^y)-y ;        //or: (x+y)^y
    }
    

    5. 求相反数

    x 的 相反数

    (~x+1)
    

    6.判断奇偶性

    a&1   = 0 偶数
    a&1   = 1 奇数
    
    Knowledge, like candlelight, can illuminate a person and countless people.
  • 相关阅读:
    jQuery代码优化的9种方法
    关于javascript代码优化的8点建议
    javascript编码标准
    前端学算法之算法复杂度
    前端学算法之算法模式
    前端学算法之搜索算法
    前端学算法之排序算法
    前端学数据结构之图
    前端学数据结构之树
    前端学数据结构之字典和散列表
  • 原文地址:https://www.cnblogs.com/xiaoqiangink/p/14366099.html
Copyright © 2011-2022 走看看