必备知识
- 计算机是以二进制方式来进行运算的,也就是0和1 。所有数据必须转化成0、1代码计算机才能识别。
- 在计算机系统中,数值,一律采用
补码
表示和存储。- 计算机中的数均放在寄存器中,通常称寄存器的位数为机器字长。
- 无符号数:既没有符号(+,-)的数,在寄存器中的每一位均可以用来存放数值。
- 有符号数:带正负号(+,-)的数,需要留出位置存放符号,“0”表示“正”,“1”表示“负”。
- 因此,在机器字长相同时,无符号和有符号数对应的数值范围是不同的。如机器字长为16位,无符号表示范围0 ~ 65535,有符号-32768 ~ +32767。
- 正数:
正整数的原码、反码和补码是一样的。
即看到符号位(第一位)是0,就可以照着写出其他两种码。
- 负数:
- 原码转换为反码:符号位不变,数值位分别“按位取反”
- 反码转换为原码也是一样:符号位不变,数值位分别“按位取反”
- 原码转换为补码:符号位不变,数值位按位取反,末位再加1
- 补码转换为原码:符号位不变,数值位按位取反,末位再加1
即补码的补码等于原码- 求补(变补),即已知[X]补,求[-X]补 。
符号位和数值位都取反,末位再加1
算术移位
算术是带有符号的数据,所以我们不能直接移动所有的位数,这可能会使得符号不正确。
算术左移时,符号位不变。它的规则是将二进制数整体向左移动,高位丢弃,低位补 0。
算术右移时,符号位是保持不变的。它的规则是将二进制数整体向右移动,低位丢弃,高位(符号位)补符号位的值。
总结:算术右移会保持符号位不变,而算术左移不保证符号位,可能会导致符号改变。
不同码制机器数算术移位后的空位添补规则
真值 | 码制 | 添补代码 |
---|---|---|
正数 | 原码、反码、补码 | 0 |
负数 | 原码 | 0 |
负数 | 补码 | 左移添0 |
负数 | 补码 | 右移添1 |
负数 | 反码 | 1 |
举例说明:
正数:不论是原码反码补码,左移还是右移,添补代码都是0.
负数的补码:左移时低位补0(右边),右移时高位补1(左边).
逻辑移位
无符号数的移位称为逻辑移位
对于逻辑移位,就是不考虑符号位,移位的结果只是数据所有的位数进行移位
规则:
左移时,高位移丢,低位添0;右移时,低位移丢,高位添0。
用例子说话
Java中整型(int)4个字节,一个字节8位,即32位。
二进制中最高位是符号位, 1 代表负数,0 代表正数。
7:
原码:0000 0000 0000 0000 0000 0000 0000 0111
反码:0000 0000 0000 0000 0000 0000 0000 0111
补码:0000 0000 0000 0000 0000 0000 0000 0111
-7:
原码:1000 0000 0000 0000 0000 0000 0000 0111
反码:1111 1111 1111 1111 1111 1111 1111 1000
补码:1111 1111 1111 1111 1111 1111 1111 1001
算术右移:
7>>2
-7>>2
算术左移:
7<<2
-7<<2
逻辑右移:
7>>>2
-7>>>2
那么问题来了:为什么1<<31答案是负数?
总结
Java中:
<<算术左移
>>算术右移
>>>逻辑右移
逻辑左移=算数左移,每次移动,右边统一添0。
逻辑右移,不管符号位,左边统一添0.比如一个有符号位的8位二进制数11001101,如果移一位就变01100110.
算数右移,左边添加的数和符号有关。
补充:
- 二进制的最高位是符号位:0表示正数,1表示负数
- 0的反码,补码都是0
- java没有无符号数,换言之,java中的数都是有符号的
- 在计算机运算的时候,都是以
补码
的方式来运算的.- 当我们看运算结果的时候,要看他的
原码
(重点)。- java 中有 7 个位运算(&、|、^、~、>>、<<和 >>>)(以补码运算,转原码看结果)
按位与&:两位全为1,结果为1,否则为0
按位或|:两位有一个为1,结果为1,否则为0
按位异或^:两位一个为0,一个为1,结果为1,否则为0
按位取反~:0->1 ,1->0