位运算

在说位运算之前,先说一下二进制的特殊问题:

 

计算机数据的存储使用二进制补码形式存储,并且最高位是符号位,1是负数,0是正数。

规定:正数的补码与反码、原码一样,称为三码合一;

负数的补码与反码、原码不一样:

负数的原码:把十进制转为二进制,然后最高位设置为1

负数的反码:在原码的基础上,最高位不变,其余位取反(0变1,1变0)

负数的补码:反码+1

例如:byte类型(1个字节,8位)

25 ==> 原码 0001 1001 ==> 反码 0001 1001 -->补码 0001 1001

-25 ==>原码 1001 1001 ==> 反码1110 0110 ==>补码 1110 0111

底层是用加法代替减法:-128==》-127-1==》-127+(-1)

-127- -1 ==> -127 + 1

1.位运算的符号

(1)左移:<<   PS :左移无论正负都是补0
(2)右移:>>   PS:当为正数时补0,负数时补1
(3)无符号右移:>>>    PS:补0
(4)按位与:&
(5)按位或:|
(6)按位异或:^
(7)按位取反:~

PS:   &、|、^是逻辑运算符还是位运算符,看它们的操作数是整数就是位运算符,是boolean就是逻辑运算符。

(以代码为基础进行讲解)

class Bit{
	public static void main(String[] args){
		//简单的算:左移几位,相当于乘以2的几次方
		//2 * 2的5次
		//实际的算:
		//2的补码: 0000 0000 0000 0000 0000 0000 0000 0010
		//2<<5:    000 0000 0000 0000 0000 0000 0010 0 0000 左边的被移走,右边补0
		System.out.println(2 << 5);
	
		//简单的算:右移几位,相当于除以2的几次方,如果除不尽,向下取整
		//250 / 2的5次  
		//实际的算:
		//250的补码 0000 0000 0000 0000 0000 0000 1111 1010
		//250>>5    0000 0 0000 0000 0000 0000 0000 0000 111  右边被移走了,左边补0
		System.out.println(250 >> 5);
		
		//简单的算:右移几位,相当于除以2的几次方,如果除不尽,向下取整
		//实际的算:
		//-250的
		//原码:1000 0000 0000 0000 0000 0000 1111 1010
		//反码:1111 1111 1111 1111 1111 1111 0000 0101
		//补码:1111 1111 1111 1111 1111 1111 0000 0110
		//-250>>5	11111 1111 1111 1111 1111 1111 1111 000 右边被移走了,左边补1
		//结果补码:11111 1111 1111 1111 1111 1111 1111 000
		//反码:11111 1111 1111 1111 1111 1111 1110 111
		//原码:10000 0000 0000 0000 0000 0000 0001 000
		System.out.println(-250 >> 5);//-8
		
		//正数的无符号右移和右移是一样的
		System.out.println(250 >>> 5);//7
		//负数的无符号右移是不同的,当右边被移走了,左边无论最高位是什么都补0
		//-250的
		//原码:1000 0000 0000 0000 0000 0000 1111 1010
		//反码:1111 1111 1111 1111 1111 1111 0000 0101
		//补码:1111 1111 1111 1111 1111 1111 0000 0110
		//-250>>>5
		//000001111 1111 1111 1111 1111 1111 000
		//最高位是0,说明是正数
		//结果的补码也是原码,000001111 1111 1111 1111 1111 1111 000
		System.out.println(-250 >>> 5);//134217720
		
		/*
		250的补码 0000 0000 0000 0000 0000 0000 1111 1010
		234的补码 0000 0000 0000 0000 0000 0000 1110 1010
		250 & 234 0000 0000 0000 0000 0000 0000 1110 1010 234
		0 & 0 是0
		0 & 1 是0
		1 & 0 是0
		1 & 1 是1
		*/
		System.out.println(250 & 234);//234
		/*
		250的补码 0000 0000 0000 0000 0000 0000 1111 1010
		234的补码 0000 0000 0000 0000 0000 0000 1110 1010
		250 | 234 0000 0000 0000 0000 0000 0000 1111 1010 250
		0 | 0 是0
		0 | 1 是1
		1 | 0 是1
		1 | 1 是1
		*/
		System.out.println(250 | 234);//250
		/*
		250的补码 0000 0000 0000 0000 0000 0000 1111 1010
		234的补码 0000 0000 0000 0000 0000 0000 1110 1010
		250 ^ 234 0000 0000 0000 0000 0000 0000 0001 0000 
		0 ^ 0 是0
		0 ^ 1 是1
		1 ^ 0 是1
		1 ^ 1 是0
		*/
		System.out.println(250 ^ 234);//16
		
		/*
		3的补码:0000 0000 0000 0000 0000 0000 0000 0011
		~3	     1111 1111 1111 1111 1111 1111 1111 1100
		结果的补码:1111 1111 1111 1111 1111 1111 1111 1100
			  反码:1111 1111 1111 1111 1111 1111 1111 1011
			  原码:1000 0000 0000 0000 0000 0000 0000 0100
		*/
		System.out.println(~3);//-4
	}
}

贴一张运算符优先级的表:

    位运算

上一篇:Unix Shell范例精解---AWK练习(上)


下一篇:proxmox超融合集群无故障运行超过250天