位运算:
程序中所有数在计算机内存中都是以二进制的形式存储的,就是直接对整数在内存中的二进制位进行操作,由于直接对内存进行操作,不需要转成十进制,因此处理速度非常快。
常见的小规则:
1. & 按位与 (and运算): 两位同时为1才返回1
一个数&1 结果就是取二进制最末尾。可以判断一个整数的奇偶,二进制末尾为0表示偶数,为1表示奇数。
2. | 按位或 (or操作):只要有一位为1即返回1
常用于二进制特定位上无条件赋值。 一个数 | 1 把二进制最末尾强行变成1。
3. ^ 按位异或 (xor操作):两位相同返回0,不同返回1。
最常用性质: a ^ b ^ b = a 应用: 可以进行简单的加密
4. ~ 取反(not运算):0、 1取反
5. << 左移(shl运算):a << b a转2进制后左移b位,后面添加0。
实际意义: 100 << 2 = 400 a乘以2的b次方,因为在二进制数后添一个0就相当于这个数乘以2。
a shi 1 比 a * 2更快,底层中尽量用。
6. >> 右移(shr运算):a >>b a除以2的b次方(取整)。
实际意义:shr 1 来代替 div 2 ,如二分查找,堆插入,求最大公约数的二进制算法用除以2代替mod。会大大提高效率。
去掉最后一位 | 101101——10110 | x >> 1 |
最后加一个0 | x << 1 | |
最后加一个1 | 101101——1011011 | x << 1 + 1 |
最后一位变成1 | x | 1 | |
最后一位变成0 | x | 1 - 1 | |
最后一位取反 | 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)) |
取末三位 注 | 101101——101 | x & 7 |
取末k位 注 | 关键是要找到末尾k个1 | x & (~(~0 << k)) |
取右边第k位 | x & (1 << ( k-1)) | |
把末k位变成1 注 | 找到末尾的1,然后或一下 | x | ((1<<k) -1 ) |
练习不在多,而抓住本质就好。
如思路最后两道:
取末k位:那么首先就可以知道末k为都1,其余位0的然后与一下就可以了。那么怎么取末k为1,其它为0, 全是1的相左走k位,然后取反就得到了。
把末k位变成1:找到末k位为1,其它为0的然后或一下
实战: 取二进制从右到左的p位置,面向右数n个二进制位。 如 1637,二进制为11001100101,这里p取7,n取5输出为11001
public static void main(String[] args) {
System.out.println(Integer.toBinaryString(1637));
int i = 1637, p = 7, n = 5;
// 去掉不要的右边几位
i = i >> (p - n);
// 取右边n位
i = i & ~(~0 << n);
System.out.println(Integer.toBinaryString(i));
}