位运算
1)概念
1】& 与运算 两个位都是 1 时,结果才为 1,否则为 0
2】| 或运算 两个位都是 0 时,结果才为 0,否则为 1
3】^ 异或运算,两个位相同则为 0,不同则为 1
4】~ 取反运算,0 则变为 1,1 则变为 0
5】<< 左移运算,向左进行移位操作(乘),高位丢弃,低位补 0
int a = 8;
a << 3;
移位前:0000 0000 0000 0000 0000 0000 0000 1000
移位后:0000 0000 0000 0000 0000 0000 0100 0000
6】右移运算,向右进行移位操作,对无符号数,高位补 0,对于有符号数,高位补符号位
unsigned int a = 8;
a >> 3;
移位前:0000 0000 0000 0000 0000 0000 0000 1000
移位后:0000 0000 0000 0000 0000 0000 0000 0001
int a = -8;
a >> 3;
移位前:1111 1111 1111 1111 1111 1111 1111 1000
移位前:1111 1111 1111 1111 1111 1111 1111 1111
2)位运算计算补充
2.1】右移运算符
将一个二进制数按指定移动的位数向右移动。移动过程中,正数最高位补0,负数最高位补1,无符号数最高位补0
2.2】补码
在计算机系统中数值一律用补码来表示和存储,其中最高位表示符号位,1表示负数,0表示正数。
正数的补码是原码自身。
负数补码是通过原码计算得到,计算过程为:符号位不变,其余位按照原码取反加1
2.3】补码计算示例
以计算十进制-100的补码为例,计算过程为:
-100的原码:10000000 00000000 00000000 01100100
符号位保持不变,取反:11111111 11111111 11111111 10011011
加1后,-100补码为:11111111 11111111 11111111 10011100
补码=~原码+1
感觉数的右移均对补码进行操作,正数对补码进行操作后就是源码,负数操作后还要再~,+1转换成源码。
正数右移
正数右移高位需补0,以100右移4位为例:
操作 二进制 对应十进制
补码 00000000 00000000 00000000 01100100 100
右移4位 00000000 00000000 00000000 00000110 6
源码 00000000 00000000 00000000 00000110 6
最后可得: 100 >> 4 = 6
正数的右移相当于除法,右移几位就除以2的几次方,如100>>4 等效 100/2^4
负数右移
负数右移高位需补1,以-100右移4位为例:
操作 二进制 对应十进制
原码 10000000 00000000 00000000 01100100 -100
转换为补码 11111111 11111111 11111111 10011100 -100
右移4位,高位补1 11111111 11111111 11111111 11111001
保留符号位,按位取反 10000000 00000000 00000000 00000110
加1后转为源码 10000000 00000000 00000000 00000111 -7
最后可得: -100 >> 4 = -7
负数的右移不等于除法,即负数右移不能按除以2的n次方计算(n表示移动位数)。
无符号右移
无符号右移和正数右移相同,都是高位补0,以-100右移4位为例:
操作 二进制 对应十进制
原码 10000000 00000000 00000000 01100100 -100
转换为补码 11111111 11111111 11111111 10011100 -100
右移4位,高位补0 00001111 11111111 11111111 11111001
转为原码 00001111 11111111 11111111 11111001 268435449
最后可得: -100 >>> 4 = 268435449
右移28位后,最高位为0表示正数,所以原码即为补码本身。
“>>>”是Java里的无符号右移操作符。