Java 位运算一些技巧

223 阅读3分钟

位运算

位与 &   = 真真为真,真假为假,假假为假
位或 |   = 真真为真,真假为真,假假为假,有一个真为真
位非 ~   = 取反码
位异或^  = 真真为假,真假为真,假假为假,相同则为假

判断一个数的奇偶

#true奇数  false偶数
boolean OddNumber =  (n&1) == 1;

判断奇偶数,只需要判断最后一位二进制是不是1。
如果二进制最后一位是1,代表是奇数。
如果二进制最后一位是0,代表是偶数。

不用中间变量,交换2个值

第一个方法:
int a = 10;   
int b = 20; 
a = a + b; //a=10+20=30; a等于20
b = a - b; //b=20-10=10; b已经交换
a = a - b; //a=30-10=20; a已经交换


第二个方法(推荐,效率高):
int a = 10;    //10的二进制=01010
int b = 20;    //20的二进制=10100
a = a ^ b; //【1】
b = a ^ b; //【2】
a = a ^ b; //【3】

^异或运算法则:
x^x=0   //如果两个值相同,异或结果为0
0^0=0
x^0=x   //



把【1】代入【2】中得到:b = (a ^ b) ^ b =  a ^ 0 = a //这里就把a的值赋给了b;
把【2】代入【3】中得到:a = (a ) ^ (a ^ b) =  b      //这里就把b的值赋给了a;

第一步:a = a ^ b; //【1】
  01010
  10100
a=11110   //这里步其实可以的得到a的二进制=11110,10进制为30

第二步:b = a ^ b; //【2】
  11110  //将第一步a的结果代入
  10100
b=01010  //这里步其实可以的得到b的二进制=01010,10进制为10,这里就已经发生互换

第三步:b = a ^ b; //【3】
  11110  //将第一步a的结果代入
  01010  //将第二步b的结果代入
a=10100  //这里步其实可以的得到a的二进制=10100,10进制为20,这里就已经发生互换

找出没有重复的数字或字母

给定一个**非空**整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。
找出那个只出现了一次的元素。

^异或根据这个规律:
x^x=0
x^0=x

如果数据是成对出现,相当于会消除掉。所有数据全部异或一下,剩下那个就是需要找的数字
class Solution {
    public int singleNumber(int[] nums) {
       int result=0;
       for(int num:nums){
           result = result ^ num;
       }
       return result;
    }
}

左移一位,相当于乘以2的运算

int num = n<<1;
比如num=10,  二进制是 1010
左移一位相当于二进制为 10100=20,//左移一位相当于*2
左移两位相当于二进制为101000=40,//左移一位相当于*2*2,即乘4


@Test
public void testLeft() {
    int positive = 100;
    int positiv_left_one = positive << 1;
    int positiv_left_two = positive << 2;
    log.info("正式positive={},左移一位={},左移两位={}", positive, positiv_left_one, positiv_left_two);
    int negative = -100;
    int negative_left_one = negative << 1;
    int negative_left_two = negative << 2;
    log.info("负数negative={},左移一位={},左移两位={}", negative, negative_left_one, negative_left_two);
}


10:11:01.138 [main] INFO 位运算.TestBinary - 正式positive=100,左移一位=200,左移两位=400
10:11:01.144 [main] INFO 位运算.TestBinary - 负数negative=-100,左移一位=-200,左移两位=-400

右移一位,相当于除以2的运算

@Test
public void testRight() {
    int positive = 100;
    int positiv_right_one = positive >> 1;
    int positiv_right_two = positive >> 2;
    log.info("正式positive={},右移一位={},右移两位={}", positive, positiv_right_one, positiv_right_two);
    int negative = -100;
    int negative_right_one = negative >> 1;
    int negative_right_two = negative >> 2;
    log.info("负数negative={},右移一位={},右移两位={}", negative, negative_right_one, negative_right_two);
}

11:22:18.113 [main] INFO 位运算.TestBinary - 正式positive=100,右移一位=50,右移两位=25
11:22:18.120 [main] INFO 位运算.TestBinary - 负数negative=-100,右移一位=-50,右移两位=-25
\TeX x^2^

二进制转10进制

214的二进制= 1 1 0 1 0 1 1 0

(从右边往左计算2的几次方,从0次方开始)

= 1*272^7 + 1*262^6 + 0*252^5 + 1*242^4 + 0*232^3 + 1*222^2+ 1*212^1+ 0*202^0

= 128 + 64 + 0 + 16 + 0 + 4 + 2 + 0

= 214

按位与&

位与 & = 真真为真,真假为假,假假为假

&&&&
第一个数0011
第二个数1001
结果0001

位或 |

位或 | = 真真为真,真假为真,假假为假,有一个真为真

||||
第一个数0011
第二个数1001
结果1011

位非 ~

位非 ~ = 取反码

~~
操作数00
结果11

位异或^

位异或^ = 真真为假,真假为真,假假为假,相同则为假

^^^^
第一个数0011
第二个数1001
结果1010