本文中所提到的运算都是基于整数来说的,因为只有整数(包括正数和负数)在操作系统中是以二进制的补码形式运算的,关于原码、反码、补码、位运算、移位运算的背景这里不再介绍,网上资料很多,感兴趣的可自行搜索。
java中能表示整数数据类型的有byte、short、char、int、long,在计算机中占用的空间使用字节描述,1个字节使用8位二进制表示。
数据类型 | 字节数 | 二进制位数 | 表示范围 | 默认值 |
---|---|---|---|---|
byte | 1 | 8 | -2^7 -- 2^7-1 | 0 |
char | 2 | 16 | 0 -- 2^16-1 | '\u0000' (代表字符为空 转成int就是0) |
short | 2 | 16 | -2^15 -- 2^15-1 | 0 |
int | 4 | 32 | -2^31 -- 2^31-1 | 0 |
long | 8 | 64 | -2^63 -- 2^63-1 | 0L |
原码、反码、补码
使用位运算前需要先弄清楚这几个概念
原码
原码也叫机器码,整数的二进制形式表示,最高位为符号位。1表示负数,0表示正数,除去符号位后剩余其他的所有位是该整数的绝对值的二进制值。
int a = 7; //原码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//原码二进制表示为:10000000 00000000 00000000 00000111
反码
反码需要区分是正数还是负数,正数的反码跟原码相同,负数的反码是除符号位外,其他位取反(即负数的最高位是1不变,其他位0变成1,1变成0)。
int a = 7; //反码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//反码二进制表示为:11111111 11111111 11111111 11111000
补码
补码也需要区分是正数还是负数,正数的补码跟原码相同,负数的补码是反码最低位加1。
int a = 7; //补码二进制表示为:00000000 00000000 00000000 00000111
int b = -7;//补码二进制表示为:11111111 11111111 11111111 11111001
说完了概念,其实这里的原码是方便给人看的,对于计算机运算来说都是使用补码
形式操作。以下的位运算和移位运算都是基于补码进行的。
位运算
位运算术语解释
位运算符 | 含义 | 解释 | 备注 |
---|---|---|---|
& | 按位与 | 两个整数按位对齐,当对齐的两位同时为1则结果为1,否则为0 | |
| | 按位或 | 两个整数按位对齐,当对齐的两位只要有一个为1则结果为1,否则为0 | |
~ | 按位非 | 只能适用于一个整数的自身操作,按位取反,即1变成0,0变成1 | 单目运算符 |
^ | 按位异或 | 两个整数按位对齐,当对齐的两位相同时为0,否则为1 |
位运算示例
我们以上面的int a = 7和int b = -7举例位运算的操作。
a的补码二进制为:00000000 00000000 00000000 00000111
b的补码二进制为:11111111 11111111 11111111 11111001
1、a&b
按位与的结果补码为:00000000 00000000 00000000 00000001
因为最高位为0,所以为正数,`正数的原码反码补码都相同`,所以原码也为:
00000000 00000000 00000000 00000001
转换成十进制的结果就是1。
2、a|b
按位或的结果补码为:11111111 11111111 11111111 11111111
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111110
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000001
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是1,所以最后按位或的结果就是-1。
3、a^b
按位或的结果补码为:11111111 11111111 11111111 11111110
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11111101
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00000010
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是2,所以最后按位或的结果就是-2。
4、~a
取反结果(补码形式):11111111 11111111 11111111 11111000
最高位为1,所以是负数。
反码=补码-1,得到反码:11111111 11111111 11111111 11110111
原码=反码除符号位取反,得到原码:10000000 00000000 00000000 00001000
由原码最高位为1可知,该结果是负数,除符号位外转换成十进制的结果是8,所以最后按位或的结果就是-8。
5、~b
取反结果(补码形式):00000000 00000000 00000000 00000110
最高位为0,所以是正数。正数的原码反码补码都相同,所以转换成十进制结果为6。
位运算应用于boolean操作
&(与)、|(或)这两个位运算适用于boolean判断,在这两个运算符的前后的条件都会计算,不像java里的条件判断符&&
(并且) ||
(或者)会短路,判断符之前的满足条件后,那么判断符之后的表达式不再计算。
public static void main(String[] args) {
int a = 5;
if (a < 0 & a++ > 0) {
}
System.out.println("&条件后a=" + a);
if (a > 0 | a++ > 0) {
}
System.out.println("|条件后a=" + a);
if (a < 0 && a++ > 0) {
}
System.out.println("&&条件后a=" + a);
if (a > 0 || a++ > 0) {
}
System.out.println("||条件后a=" + a);
}
输出结果为:
&条件后a=6
|条件后a=7
&&条件后a=7
||条件后a=7
第一个判断a < 0 & a++ > 0
前一个判断已经是false了,但是使用&
连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于6。
第二个判断a > 0 | a++ > 0
前一个判断已经是true了,但是使用|
连接,后一个表达式依然会计算a++,所以输出结果a的值加1等于7。
第三个判断a < 0 && a++ > 0
前一个判断已经是false了,使用&&
连接的不会再计算后一个表达式的值,所以a的值不变。
第四个判断a > 0 || a++ > 0
前一个判断已经是true了,使用||
连接的不会再计算后一个表达式的值,所以a的值不变。
移位运算
移位运算术语解释
移位运算符 | 含义 | 解释 |
---|---|---|
<< | 左移 | 补码高位(不包括 |
首页 上一页 1 2 下一页 尾页 1/2/2 | |
【大 中 小】【打印】 【繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部】 | |
上一篇:一种轻量级定时任务实现 | 下一篇:号称取代 Elasticsearch,太猛了! |