Java基础语法(六) 运算符
五、 位运算符
位运算符用来对二进制位进行操作,计算机内部是用补码表示数,位运算是对数的补码进行运算
位运算符是对long、int、short、byte和char这5种类型的数据进行运算的,我们不能对double、float和boolean进行位运算操作。
上述内容翻译过来就是:第一、位运算是干什么的;第二、位运算可以操纵的数据类型。
由于很少用到,(大神说的,我也不知道是不是),所以大家了解一下即可。
Java的位运算符,详见下表:
位运算符 | 名称 | 释义 |
& | 按位与 | 任何二进制位和0进行&运算,结果是0;和1进行&运算,结果是原值 |
∣ | 按位或 | 任何二进制位和0进行∣运算,结果是原值;和1进行∣运算结果是1 |
^ | 按位异或 | 任何相同二进制位进行^运算,结果是0;不相同 二进制位进行^运算,结果是1 |
~ | 按位取反 | 正数取反,各二进制码按补码各位取反。负数取反,各二进制码按补码各位取反 |
<< | 左移 | 空位补0,被移除的最高位丢弃 |
>> | 右移 | 被移位的二进制最高位是0,右移后,空缺位补0;最高位是1,空缺位补1 |
>>> | 无符号右移 | 被移位二进制最高位无论是0或者是1,空缺位都用0补 |
(一) &、 | 、^、~
上述符号,依次为按位与、按位或、按位异或、按位取反。
为了简单明了,我根据各个运算符的特点,把它们分成两大部分来讲解。
第一反应是乱码或者想歪了的小伙伴,请先行面壁。
public class demon {
public static void main(String[] args) {
int a=3;
int b=4;
System.out.println(3&4);
System.out.println(3|4);
System.out.println(3^4);
System.out.println(~3);
}
}
解题思路:
1、由于是位运算,所以必须先把数据转换成二进制再求补码,但正数的原码、补码、反码都相同,
所以3的二进制是11,但int类型占4个字节,32个比特位:
00000000 00000000 00000000 00000011
4的二进制是100:
00000000 00000000 00000000 00000100
2、根据 &位运算 的要求:任何二进制位和0进行&运算,结果是0;和1进行&运算,结果是原值。
3&4= 0
00000000 00000000 00000000 00000011
&
00000000 00000000 00000000 00000100
…………………………………………………………………
00000000 00000000 00000000 00000000
由此可见,&运算的规则可以简化为有0则0
3、根据 | 运算要求:任何二进制位和0进行∣运算,结果是原值;和1进行∣运算结果是1。
3 | 4= 7
00000000 00000000 00000000 00000011
|
00000000 00000000 00000000 00000100
…………………………………………………………………
00000000 00000000 00000000 00000111
由此可见,| 运算的规则可以简化为有1则1
4、根据 ^ 运算要求:任何相同二进制位进行^运算,结果是0;不相同二进制位。
3^4=7
00000000 00000000 00000000 00000011
^
00000000 00000000 00000000 00000100
…………………………………………………………………
00000000 00000000 00000000 00000111
由此可见,^ 运算的规则可以简化为相同则0,不同则1
5、根据 ~ 运算要求:正数取反,各二进制码按补码各位取反。负数取反,各二进制码按补码各位取反。
~3= -4
~00000000 00000000 00000000 00000011
…………………………………………………………………
11111111 111111111 111111111 11111100
此时的结果是“补码”,但计算机平时呈现在人类眼前的是原码,所以我们还需针对补码求原码。
补码: 11111111 111111111 111111111 11111100
反码: 11111111 111111111 111111111 11111011
原码:10000000 00000000 00000000 00000100
由此可见,~ 运算的规则可以简化为0变1,1变0
运行后的结果与上述推导吻合。
但不知道大家有没有发现这几个位运算符和前面的逻辑运算符长相一样?
那么作为一名小白,我怎么知道啥时候它们是位运算符,啥时候又是逻辑运算符呢?
((a>b)&(a>c))
(3&4)
仔细看看,这两组的区别在哪里。
……一……二……三
我要说结果啦:
当符号两边是变量的时候,它是逻辑运算符,当符号两边是常量(数据)的时候,它是位运算符。
阿辣嗖?
(二) <<、>> 、 >>>
上述符号依次为:左移、右移、无符号右移。
接着举栗子
public class demon {
public static void main(String[] args) {
System.out.println(3<<2);
System.out.println(24>>2);
System.out.println(24>>>2);
}
}
解题思路:
1、3<<2
计算出3的二进制11,求其补码(正数原码、补码、反码相同)
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 00000011
根据空位补0,被移除的最高位丢弃规则,括号里的两位二进制被丢弃,后续顺序向左移,然后在右边空出的两个位置补0,即:
00000000 00000000 00000000 00001100=12(十进制)
2、24>>2
计算出24的二进制11000,求其补码(正数原码、补码、反码相同)
00000000 00000000 00000000 00011000
00000000 00000000 00000000 000110(00)
根据 被移位的二进制最高位是0,右移后,空缺位补0;最高位是1,空缺位补1规则,括号里的两位二进制被丢弃,后续顺序向右移,然后在左边空出的两个位置补0,即:
00000000 00000000 00000000 00000110=6(十进制)
3、24>>>2
00000000 00000000 00000000 00011000
根据被移位二进制最高位无论是0或者是1,空缺位都用0补,结果为:
00000000 00000000 00000000 00000110=6(十进制)
运行后的结果与我们推导一致。
看到这里估计爱动脑筋的小伙伴已经发现,3<<2和24>>2的结果与原始数据之间的规律,在这里我们就不卖关子,直接给出:
<<就是把左移的数据,乘以2的移动次幂
所以3<<2=32^2=34=12
>> 就是把右移的数据,除以2的移动次幂
所以24>>2=24/2^2=24/4=6
以上所有例子我们为了方便,都用了正数,那么如果题目改为 -24>>2呢?
(三)、面试题
文章读到此,是不是觉得“还好”、“轻轻松松”?
那好,接下来准备接受现实无情的打击吧。👸👸👸
1、请用最有效率的方式,写出2乘以8的结果;
2、请自己实现两个整数变量的交换;
第一题比较简单,我直接说结果:2<<3
下面我们好好来看看第二题,根据题目要求,先定义两个变量:
public class demon {
public static void main(String[] args) {
int a=10;
int b=20;
}
}
所谓两个变量的交换,无非是让变量a=20,变量b=10而已,其实也不难,但你能想到几种解题方法呢?(老师就是这么虐我的,没办法,我只能这么虐你😛)
……一……二……三……四……五…………………………
现在我公布答案:一共四种解题方式
方法一、使用第三方变量
public class demon {
public static void main(String[] args) {
int a=10;
int b=20;
int c=a;
a=b;
b=c;
System.out.println("a:"+a+",b:"+b);
}
}
其实这里相当于用一个第三方变量c,把变量a的值暂时保存,然后再把变量b(20)赋值给a,这时变量a=20,再把变量c(10),赋值给变量b
方法二、用按位异或^实现
public class demon {
public static void main(String[] args) {
int a=10;
int b=20;
a=a^b;
b=a^b;
a=a^b;
System.out.println("a:"+a+",b:"+b);
}
}
不知道小伙伴们有没有发现,当一个数据对另一个数据^两次的时候,该数本身不变。
方法三、
public class demon {
public static void main(String[] args) {
int a=10;
int b=20;
a=a+b;
b=a-b;
a=a-b;
System.out.println("a:"+a+",b:"+b);
}
}
方法四、一步搞定
public class demon {
public static void main(String[] args) {
int a=10;
int b=20;
b=(a+b)-(a=b);
System.out.println("a:"+a+",b:"+b);
}
}
今天讲了这么多,就到这里吧,休息、休息一下下……