运算符
Tips:本文章的背景为Java,与其他语言可能存在一些差异。
在了解运算符之前,我们先来巩固下二进制的概念:
二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。 [1]
二进制数(binaries)是逢2进位的进位制,0、1是基本算符 [2] ;计算机运算基础采用二进制。电脑的基础是二进制。在早期设计的常用的进制主要是十进制(因为我们有十个手指,所以十进制是比较合理的选择,用手指可以表示十个数字,0的概念直到很久以后才出现,所以是1-10而不是0-9)。电子计算机出现以后,使用电子管来表示十种状态过于复杂,所以所有的电子计算机中只有两种基本的状态,开和关。也就是说,电子管的两种状态决定了以电子管为基础的电子计算机采用二进制来表示数字和数据。常用的进制还有8进制和16进制,在电脑科学中,经常会用到16进制,而十进制的使用非常少,这是因为16进制和二进制有天然的联系:4个二进制位可以表示从0到15的数字,这刚好是1个16进制位可以表示的数据,也就是说,将二进制转换成16进制只要每4位进行转换就可以了。
二进制的“00101000”直接可以转换成16进制的“28”。字节是电脑中的基本存储单位,根据计算机字长的不同,字具有不同的位数,现代电脑的字长一般是32位的,也就是说,一个字的位数是32。字节是8位的数据单元,一个字节可以表示0-255的十进制数据。对于32位字长的现代电脑,一个字等于4个字节,对于早期的16位的电脑,一个字等于2个字节。
位异或运算(^)
运算规则是:两个数转为二进制,然后从高位开始比较,如果相同则为0,不相同则为1。
位与运算(&)
运算规则:两个数都转为二进制,然后从高位开始比较,如果两个数都为1则为1,否则为0。
位或运算符(|)
运算规则:两个数都转为二进制,然后从高位开始比较,两个数只要有一个为1则为1,否则就为0。
位非运算符(~)
运算规则:如果位为0,结果是1,如果位为1,结果是0.
移位操作
算术移位
算术是带有符号的数据,所以我们不能直接移动所有的位数,这可能会使得符号不正确。
有符号左移 «
用来将一个数的各二进制位全部左移若干位。
如: 十进制数a = 10,二进制a = 1010 ,则 a « 2 = 101000;
十进制数a = -10,二进制a = 11111111111111111111111111110110 ,则 a « 2 = 11111111111111111111111111011000;
Tips:十进制数10转为二进制数为1010,十进制数-10转为二进制数为11111111111111111111111111110110,很多人便好奇为啥负数前面有这么多的1?
首先我们明确下概念:二进制最左端的数字为符号位,0代表正,1代表负。
现在知道了原来负数前面的1表示符号,那么为啥正数前面的0没了呢,实际上不是没了,只是我们习惯与省略掉0,为了方便阅读而已。
另外位数为啥是32位,文章的开始也带大家复习了二进制的概念:现代电脑的字长一般是32位的。
有符号右移 »
用来将一个数的各二进制位全部右移若干位,移到右端的低位被舍弃,最高位则移入原来高位的值。
正数:最左边都是0,移位的时候,符号保持不变,最左边依旧是填充0。
负数:最左边都是1,移位的时候,符号保持不变,最左边填充1。
如: 十进制数a = 10,二进制a = 1010 ,则 a » 2 = 10;
十进制数a = -10,二进制a = 11111111111111111111111111110110 ,则 a » 2 = 11111111111111111111111111111101;
逻辑移位
对于逻辑移位,就是不考虑符号位,移位的结果只是数据所有的位数进行移位。根据移位操作的目的,右移时,高位补0(Java中不存在逻辑左移);
无符号右移 »>
用来将一个数的各二进制位无符号右移若干位,与运算符»相同的是移出的低位被舍弃,但不同的是最高位补0。
如: 十进制数a = 10,二进制a = 1010 ,则 a »> 2 = 10 ;
十进制数a = -10,二进制a = 11111111111111111111111111110110 ,则 a »> 2 = [00]111111111111111111111111111101;([] 为了更好的标识补充的0)
最后我们将上述例子执行一遍:
public static void main(String[] args) {
System.out.println("10:" + Integer.toBinaryString(10));
System.out.println("-10:" + Integer.toBinaryString(-10));
System.out.println("10<<2运算的结果是 :" + ((10) << 2) + " " + Integer.toBinaryString((10) << 2));
System.out.println("-10<<2运算的结果是 :" + ((-10) << 2) + " " + Integer.toBinaryString((-10) << 2));
System.out.println("10>>2运算的结果是 :" + ((10) >> 2) + " " + Integer.toBinaryString((10) >> 2));
System.out.println("-10>>2运算的结果是 :" + ((-10) >> 2) + " " + Integer.toBinaryString((-10) >> 2));
System.out.println("10>>>2运算的结果是 :" + ((10) >>> 2) + " " + Integer.toBinaryString((10) >>> 2));
System.out.println("-10>>>2运算的结果是 :" + ((-10) >>> 2) + " " + Integer.toBinaryString((-10) >>> 2));
}
输出:
10:1010
-10:11111111111111111111111111110110
10<<2运算的结果是 :40 101000
-10<<2运算的结果是 :-40 11111111111111111111111111011000
10>>2运算的结果是 :2 10
-10>>2运算的结果是 :-3 11111111111111111111111111111101
10>>>2运算的结果是 :2 10
-10>>>2运算的结果是 :1073741821 111111111111111111111111111101
总结
学术名 | 符号 | 例子 | 操作 | 解释 |
---|---|---|---|---|
算术移位 | « | num« n | 用来将一个数的各二进制位全部左移若干位,低位补0。 | 相当于 num×2^n |
算术移位 | » | num»n | 用来将一个数的各二进制位全部右移若干位,高位按照符号补充,正数补充0,负数补充1。 | 相当于num/2^n |
逻辑移位 | »> | num»>n | 用来将一个数的各二进制位全部右移若干位,高位补0。 | 当num为正数时,和»一个效果;当num为负数时,高位补充0,与»不同 |