关于异或和一些运算符

上课的时候经常摸鱼,连异或都没搞懂,今天看map源码的时候才注意到有一个看不懂的计算符
 static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

就上面代码中的 ^ 号,开始一脸懵逼,以为是乘方,但想了想,先把h赋值了,然后让它 乘方 (自己除以2的16次方结果)?这多多少少有点大病吧。

所以我大概率断定这个 ^  应该不是乘方,所以就去查了查,发现是异或的意思,当初自己都没搞懂,现在又来…………罢了罢了,总得要补的,就自己去学历一下异或怎么玩,顺便还总结了一下几个计算符:

如下:

Java运算符大致分为逻辑运算符(&&,||,!)、算数运算符(+, -, *, / ,+=)、位运算符(^,|,&)、其他运算符(三元运算符)

&(按位与)

System.out.println(3&5);
System.out.println(7&5);



控制台打印:
1
5
  • &按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,运算规则即(两个为真才为真)1&1=1 , 1&0=0 , 0&1=0 , 0&0=0

 

  • 3的二进制位是0000 0011 , 5的二进制位是0000 0101 , 那么就是011 & 101,由按位与运算规则得知,001 & 101等于0000 0001,最终值为1

 

  • 7的二进制位是0000 0111,那就是111 & 101等于101,也就是0000 0101,故值为5

&&(逻辑与)

 这个没啥说的吧

&&逻辑与也称为短路逻辑与,先运算&&左边的表达式,一旦为假,后续不管多少表达式,均不再计算,一个为真,再计算右边的表达式,两个为真才为真。

|(按位或)

System.out.println(6^2);


控制台打印:

4

 

|按位或和&按位与计算方式都是转换二进制再计算,不同的是运算规则(一个为真即为真)1|0 = 1 , 1|1 = 1 , 0|0 = 0 , 0|1 = 1

6的二进制位0000 0110 , 2的二进制位0000 0010 , 110|010为110,最终值0000 0110,故6|2等于6

||(逻辑或)

这个也不需要多说什么了吧

  逻辑或||的运算规则是一个为真即为真,后续不再计算,一个为假再计算右边的表达式。

^(异或运算符)

System.out.println(9^9);
System.out.println(7^9);


控制台打印:

0
14


异或,先把计算的两个数化成2进制数,位数相同的情况下(不够拿0补)
然后按照异或法则 1^1=0 0^0=0  1^0=1 0^1=1
对应位数分别计算
比如上面的9^9   9的2进制为 1001  所以计算过程应该是: 1^1=0  0^0=0  0^0=0  1^1=0
                                再组合,结果为0000,所以结果为0
再比如:7^9   9的2进制为1001 7的二进制为111,计算过程应该是:
                                因为9的二进制是4位,所以应该先给7补位,变成0111
                               然后再分别疑惑:0^1=1  1^0=1  1^0=1  1^1=0
                               再组合为1110,所以结果应该是14
 

<<(左移运算符)

先把需要计算的数化作2进制,然后往左边移动,二进制左边移动就是乘2呗

左移多少就是乘以2的多少次方 

System.out.println(6<<2);
System.out.println(9<<3);


控制台打印:

24
72
6左移两位,就是乘以2的2次方,就是乘4,所以得24
9左移三位,就是乘以2的3次方,就是乘8,所以得72
 

>>(右移运算符)

跟左移相反,右移多少位就是除以2的多少次方

System.out.println(16>>2);
System.out.println(100>>3);


控制台打印:

4
12

这里说一下,右移是除,所以是小数,但浮点型是不能进行左右移的,所以自动转换了

 

~(取反运算符)

  说实话,我都不知道还有个取反符号!

  这个的意思是先把数转化为2进制,然后1取0 , 0取1 ,最后得到一个数,再转为10进制

  

public static String jinZhiZhuanHuan(int x, int len) {//写的一个整数转换成2进制的方法,x代表需要转换的整数,len表示需要转换的2进制位数
    final char[] buff = new char[len];
    for (int i = len - 1; i >= 0 ; i--) {
        int mask = 1 << i;
        buff[len - 1 - i] = (x & mask) != 0 ? '1' : '0';
    }

    return new String(buff);
}


 public static void main(String[] args) {
       System.out.println(jinZhiZhuanHuan(5,16));
        System.out.println(~5);
        System.out.println(jinZhiZhuanHuan(~5,16));
 }


控制台打印结果:

0000000000000101
-6
1111111111111010

所实话吧,我都不知道这个有啥用,用来加密吗?

 

>>>(无符号右移运算符)

System.out.println(15>>>2);


控制台打印:

3

正数无符号右移(和右移差不多)

无符号右移运算符和右移运算符的主要区别在于负数的计算,因为无符号右移是高位补0,移多少位补多少个0。

15的二进制位是0000 1111 , 右移2位0000 0011,结果为3

 

 

负数无符号右移

System.out.println(jinZhiZhuanHuan(~6,8));//6取反的二进制
String a =jinZhiZhuanHuan(~6,8);
int a1 =Integer.valueOf(a);
a=String.valueOf(a1+9);//取反后加1
System.out.println(a);

System.out.println(-6>>>3);
System.out.println(jinZhiZhuanHuan(-6>>>3,32));



控制台打印:

11111001
11111010
536870911
00011111111111111111111111111111

 

-6的二进制是6的二进制取反再加1,6的二进制也就是0000 0000 0000 0000 0000 0000 0000 0110,

取反后加1为1111 1111 1111 1111 1111 1111 1111 1010,

右移三位0001 1111 1111 1111 1111 1111 1111 1111

所以结果为:536870911

这里我也不太明白,就这样记录吧

 
posted @ 2022-12-23 12:11  牛杂刻师傅  阅读(167)  评论(0)    收藏  举报