Java位运算小节

2019新春支付宝红包技术大揭秘在线峰会将于03-07日开始,点击这里报名届时便可参与大牛互动。java

位运算表达式由操做数和位运算符组成,实现对整数类型的二进制数进行位运算。位运算符能够分为逻辑运算符(包括~、&、|和^)及移位运算符(包括>>、<<和>>>)。算法

1)左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。
2)“有符号”右移位运算符(>>)则将运算符左边的运算对象向右移动运算符右侧指定的位数。 “有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1。
3)Java也添加了一种“无符号”右移位运算符(>>>),它使用了“零扩展”:不管正负,都在高位插入0。这一运算符是C或C++没有的。
4)若对char,byte或者short进行移位处理,那么在移位进行以前,它们会自动转换成一个int。 只有右侧的5个低位才会用到。这样可防止咱们在一个int数里移动不切实际的位数。 若对一个long值进行处理,最后获得的结果也是long。此时只会用到右侧的6个低位,防止移动超过long值里现成的位数。 但在进行“无符号”右移位时,也可能遇到一个问题。若对byte或short值进行右移位运算,获得的可能不是正确的结果(Java 1.0和Java 1.1特别突出)。 它们会自动转换成int类型,并进行右移位。但“零扩展”不会发生,因此在那些状况下会获得-1的结果。

在进行位运算时,须要注意几点:数组

(1)>>>和>>的区别是:在执行运算时,>>>运算符的操做数高位补0,而>>运算符的操做数高位移入原来高位的值。
(2)右移一位至关于除以2,左移一位(在不溢出的状况下)至关于乘以2;移位运算速度高于乘除运算。
(3)若进行位逻辑运算的两个操做数的数据长度不相同,则返回值应该是数据长度较长的数据类型。
(4)按位异或能够不使用临时变量完成两个值的交换,也可使某个整型数的特定位的值翻转。
(5)按位与运算能够用来屏蔽特定的位,也能够用来取某个数型数中某些特定的位。
(6)按位或运算能够用来对某个整型数的特定位的值置1。

位运算符的优先级

~的优先级最高,其次是<<、>>和>>>,再次是&,而后是^,优先级最低的是|。

位运算的应用

1.判断int型变量a是奇数仍是偶数code

a&1 == 0 偶数
a&1 == 1 奇数

2.求平均值,好比有两个int类型变量x、y,首先要求x+y的和,再除以2,可是有可能x+y的结果会超过int的最大表示范围。对象

(x&y)+((x^y)>>1);
知识点:>>n 至关于除于2^n ,<<n 至关于乘于2^n 。
x,y对应位均为1,相加后再除以2仍是原来的数,如两个00001000相加后除以2仍得00001000,那么咱们把x与y分别分红两个部分来看,二者相同的位分别拿出来 则 :
x = (111111111111000)2 =  (111111111111000)2 +  (000000000000000)2
y =  (111111111111010)2 =  (111111111111000)2 +  (000000000000010)2
相同部分咱们叫作x1,y1,不一样部分咱们叫作x2,y2.那么如今(x+y)/2 =(x1+y1)/2 +(x2 + y2)/2 ,由于x1 == y1 ,因此(x1+y1)/2 ==x1 ==y1,相同部分咱们用与运算求出来 x1 = x&y ,不一样部分的和咱们用^求出来,而后除于2就是咱们想要的结果了。

3.对于一个大于0的整数,判断它是否是2的几回方支付宝

((x&(x-1))==0)&&(x!=0);
    /*若是是2的幂,n必定是100... n-1就是1111....
       因此作与运算结果为0*/

4.好比有两个int类型变量x、y,要求二者数字交换,位运算的实现方法get

x ^= y;
    y ^= x;
    x ^= y;

5.求绝对值it

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

6.取模运算,采用位运算实现table

a % (2^n) 等价于 a & (2^n - 1) ;或者 m % n 等价于 m & (n-1)

7.乘法运算 采用位运算实现class

a * (2^n) 等价于 a << n

8.除法运算转化成位运算

a / (2^n) 等价于 a>> n

9.求相反数

(~x+1)

10.a % 2 等价于

a & 1

11.取int型变量a的第k位 (k=0,1,2……sizeof(int))

a>>k&1   (先右移再与1)

12.将int型变量a的第k位清0

a&~(1<<k)    (10000 取反后为00001 )

13.将int型变量a的第k位置1

a|(1<<k)

14.int型变量循环左移k次

a<<k|a>>16-k   (设sizeof(int)=16)

15.int型变量a循环右移k次

a>>k|a<<16-k   (设sizeof(int)=16)

16.对于一个数 x >= 0,判断是否是2的幂。

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

17.不用temp交换两个整数

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

18.条件判断赋值简写

if (x == a)
        x= b;
   else
        x= a;

  等价于 x= a ^ b ^ x;

19.x的相反数

(~x+1)

20.m乘以2的n次方

m << n

21.m除以以2的n次方

m >> n

22.求整数k从x位(高)到y位(低)间共有多少个1

public static int findChessNum(int x, int y, int k) {
  int result = 0;
  for (int i = y; i <= x; i++) {
    result += ((k >> (i - 1)) & 1);
  }
  return result;
  }

23.取绝对值

int abs(int n){
      return (n ^ (n >> 31)) - (n >> 31);
  }
/* n>>31 取得n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1
若n为正数 n^0=0,数不变,若n为负数有n^-1 须要计算n和-1的补码,而后进行异或运算, 结果n变号而且为n的绝对值减1,再减去-1就是绝对值 */

24.只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次之外,其他每一个元素均出现两次。找出那个只出现了一次的元素。
说明:你的算法应该具备线性时间复杂度。 你能够不使用额外空间来实现吗?
示例 1:

输入: [2,2,1]输出: 1

示例 2:

输入: [4,1,2,1,2]输出: 4

这个题首先想到的就是异或的特性。相同的数字异或的结果为 0,那么出现奇数次的必定就是最后咱们想要的结果。

public int singleNum(int[] nums){
    int res = num[0];
    for(int i=1;i<nums.length;i++){
        res ^= nums[i];
    }
    return res;
}

总结

功能 示例 位运算
去掉最后一位 (101101->10110) x >> 1
在最后加一个0 (101101->1011010) x < < 1
在最后加一个1 (101101->1011011) x < < 1+1
把最后一位变成1 (101100->101101) x | 1
把最后一位变成0 (101101->101100) x | 1-1
最后一位取反 (101101->101100) x ^ 1
把右数第k位变成1 (101001->101101,k=3) x | (1 < < (k-1))
把右数第k位变成0 (101101->101001,k=3) x & ~ (1 < < (k-1))
右数第k位取反 (101001->101101,k=3) x ^ (1 < < (k-1))
取末三位 (1101101->101) x & 7
取末k位 (1101101->1101,k=5) x & ((1 < < k)-1)
取右数第k位 (1101101->1,k=4) x >> (k-1) & 1
把末k位变成1 (101001->101111,k=4) x | (1 < < k-1)
末k位取反 (101001->100110,k=4) x ^ (1 < < k-1)
把右边连续的1变成0 (100101111->100100000) x & (x+1)
把右起第一个0变成1 (100101111->100111111) x | (x+1)
把右边连续的0变成1 (11011000->11011111) x | (x-1)
取右边连续的1 (100101111->1111) (x ^ (x+1)) >> 1
去掉右起第一个1的左边 (100101000->1000) x & (x ^ (x-1))
判断奇数 (x&1)==1
判断偶数 (x&1)==0

点击阅读更多,查看更多详情

相关文章
相关标签/搜索