Java位运算

Java位运算

Posted by WangZiTao on Saturday, August 24, 2019

单位换算

  1. bit:位 一个二进制数据0或1,是1bit;

  2. byte:字节 1 byte = 8 bit , 存储空间的基本计量单位;

  3. 一个英文字符占一个字节 1 字母 = 1 byte = 8 bit;

  4. 一个汉字占2个字节 1 汉字 = 2 byte = 16 bit;

支持的数据类型

首先明确一点,Java中的位运算是针对整型的数据类型进行运算的,所以操作数必须是一下五种之一。

数据类型所占位数(bit)
byte8
short16
int32
long64
char16

数据存储方式

计算机中存储的数据最终是以二进制存储(补码存储),如int类型的十进制数字10表示为32bit的二进制:

0000 0000 0000 0000 0000 0000 0000 1010

注:数据在计算机中都是以反码形式存在。正数的的原码与反码相同。 有关原码、反码、补码的知识,请看另一个章节原码、反码、补码

位运算符

运算符含义
&按位与(对应位同为1时,才为1,否则全为0)
|按位或(对应位只要有1时,即为1,否则全为0)
~按位非(对每位进行取反)
^按位异或(只要对应为不同即为1)
«左移(左移 左边最高位丢弃,右边补齐0)
»右移(最高位是0,左边补齐0;最高为是1,左边补齐1)
«<无符号右移(无论操作数是正数还是负数,高位都是补0)

按位与 &

规则: 对应位同为1时,才为1,否则全为0(对应位只要有0,全为0,否则为1)

int a = 127;
int b = 128;
System.out.println("127 & 128 的结果是:"+(a & b));

运行结果:

127 & 128 的结果是:0

解析: 
127的二进制(补码):00000000 00000000 00000000 01111111
128的二进制(补码):00000000 00000000 00000000 10000000
根据 & 规则结果:  00000000 00000000 00000000 00000000
所以结果为0

按位或 |

规则: 对应位只要有1时,即为1,否则全为0(对应位只有全是0时,结果才是0,否则为1)

int a = 127;
int b = 128;
System.out.println("127 | 128 的结果是:"+(a | b));

运行结果:

127 | 128 的结果是:255

解析: 
127的二进制(补码):00000000 00000000 00000000 01111111
128的二进制(补码):00000000 00000000 00000000 10000000
根据 | 规则结果:  00000000 00000000 00000000 11111111
最高为0,为正数,原码补码一样,所以结果为255

按位非 ~

规则: 对每位进行取反

int a = 128;
System.out.println("~128 的结果是:" + ~ a);

运行结果:

~128 的结果是:-129

解析: 
128的二进制(补码):00000000 00000000 00000000 10000000
根据 ~ 规则结果:  11111111 11111111 11111111 01111111
最高为1,为负数。
补码:11111111 11111111 11111111 01111111
反码:11111111 11111111 11111111 01111110
原码:10000000 00000000 00000000 10000001
结果为 -129

按位异或 ^

规则: 只要对应为不同即为1。

int a = 127;
int b = 128;
System.out.println("127 ^ 128 的结果是:" + (a ^  b));

运行结果:

127 ^ 128 的结果是:255

解析: 
127的二进制(补码):00000000 00000000 00000000 01111111
128的二进制(补码):00000000 00000000 00000000 10000000
根据 | 规则结果:  00000000 00000000 00000000 11111111
最高为0,为正数,原码补码一样,所以结果为255

位移动运算符

左移 «

规则: « :左移 左边最高位丢弃,右边补齐0;

  • 左移的规则只记住一点:丢弃最高位,0补最低位
  • 如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模

通用格式:

value << num 
num : 指要移位值   
value : 指移动的位数。
意思是value向左位移num位,左移num位,相当于乘以2^num

例如:

int a = 1;
System.out.println("1 << 2 的结果是:" + (a << 2));

运行结果(图片来自于网络): 左移

1 << 2 的结果是:4

右移 »

规则: »:右移, 最高位是0(正数时),左边补齐0;最高为是1(正数时),左边补齐1,保持为负数;

m»n即相当于m除以2的n次方,得到的为整数时,即为结果。如果结果为小数,此时会出现两种情况:

1 如果m为正数,得到的商会无条件 的舍弃小数位;

2 如果m为负数,舍弃小数部分,然后把整数部分加+1得到位移后的值。

通用格式:

value >> num 
num : 指要移位值   
value : 指移动的位数。
意思是value向左位移num位,左移num位,相当于除以2^num

例如:

int a = 12;
System.out.println("12 >> 2 的结果是:" + (a >> 2));

运行结果(图片来自于网络,图中稍有错误,其中10应该为12): 右移

1 << 2 的结果是:4

无符号右移 »>

无符号右移»> 与 右移» 的区别就是无论操作数是正数还是负数,高位都是补0

int a = 12;
System.out.println("12 >>> 2 的结果是:" + (a >>> 2));

int b = -12;
System.out.println("-12 >>> 2 的结果是:" + (b >>> 2));

运行结果:

12 >>> 2 的结果是:3
-12 >>> 2 的结果是:1073741821

解析: 
12 >>> 2 跟 12 >> 2 过程一样,上面有过程,我们说下 -12 >>> 2
-12的原码:        10000000 00000000 00000000 00001100
-12的二进制(补码): 11111111 11111111 11111111 11110100
右移2位:           11111111 11111111 11111111 11110100
补齐:            0011111111 11111111 11111111 111101
注意这个补齐因为是无符号的,最高位补0,结果为正数
最高为0,为正数,原码补码一样,所以结果为的结果是:1073741821

comments powered by Disqus