原码、反码、补码
- 原码:十进制数据的二进制表现形式,最左边的是符号位,0为正,1为负。
- 反码:正数的反码是其本身,负数的反码是符号位保持不变,其余取反。
- 补码:正数的补码是其本身,负数的补码是在其反码的基础上+1
什么是原码
十进制数据的二进制表现形式,最左边的是符号位,0为正,1为负。
- 比如说56(10) 转成 00111000(2)
其中将这个二进制数据拆解开:变成0 0111000
第一个0是符号位,后面的是数据。
-
在计算机中一个字节(B)占8个bit即8个比特位
一个字节最大值是:01111111:即1个0七个1
这是因为第一个0代表的是符号位而不是数据!故一个字节最大值是+127
一个字节的最小值是:11111111:即1个1加7个1
故最小值是-127
综上::十进制数据的二进制表现形式,最左边的是符号位,0为正,1为负。
-
原码的弊端:
利用原码对正数进行计算不会出现问题,但是用原码对负数进行计算有特殊情况
举例:
给定一个 -0(10),他的原码为:10000000
那么 -0(10)+1(10)=1,但在原码中!10000000变成10000001这样的出来的却是-1
在这个原码基础上往上继续-1+1实际应该=0但原码中为:10000010 即-2
这就是原码的弊端:如果利用原码进行负数计算,结果会出现错误,实际结果会跟我们预期的结果相反。
什么是反码
反码:为了解决原码不能计算负数的问题出现的。
计算规则:正数的反码不变,负数的反码在原码的基础上,符号位不变。数值取反,其他取反
举例:
-56(10) 转成原码: 10111000
-56(10)转成反码:11000111
用-56(10)+1就变成了:11001000
更详细的看表:
十进制数 | 原码 | 反码 |
---|---|---|
+0 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 |
-1 | 1000 0001 | 1111 1110 |
-2 | 1000 0010 | 1111 1101 |
-3 | 1000 0011 | 1111 1100 |
-4 | 1000 0100 | 1111 1011 |
-5 | 1000 0101 | 1111 1010 |
-6 | 1000 0110 | 1111 1001 |
-7 | 1000 0111 | 1000 1000 |
从上表中不能看出,当反码的计算出现跨0的情况就会出现错误!
反码的弊端:
比如说
-5+6=1但是反码中: 1111 1010 + 0000 0110= 0000 0000 这个结果却为0而不是1
这个是因为:在反码中0有俩种表现形式,当负数计算出现时如果结果跨0了就会比预期的少了1
就多跨了1个1
补码
为了解决反码中出现跨0计算时实际结果比预期结果少了1的情况
计算规则:正数的补码是其本身,负数的补码是负数的反码+1
如表
十进制数 | 原码 | 反码 | 补码 |
---|---|---|---|
+0 | 0000 0000 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 | 0000 0000 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
-2 | 1000 0010 | 1111 1101 | 1111 1110 |
-3 | 1000 0011 | 1111 1100 | 1111 1101 |
-4 | 1000 0100 | 1111 1011 | 1111 1100 |
-5 | 1000 0101 | 1111 1010 | 1111 1011 |
-6 | 1000 0110 | 1111 1001 | 1111 1010 |
-7 | 1000 0111 | 1000 1000 | 1111 1001 |
故数字在计算机中的存储都是以补码的形式来进行的
补码的小细节:
因为补码中节约了一个-0的空间,故可以多出一个 -128
它的补码是1000 0000
-128没有原码没有反码。
这就是为什么在计算机中一个字节的范围为 -128到+127
隐式类型转换的原理
byte a=10;//10的补码0000 1010
int b=a;//因为int是4字节而byte是1个字节故将byte前面补3个字节即可
//相当于0000 0000 0000 0000 0000 0000 0000 1010
//就前面补0
强制类型转换的原理
情况1
int a=300;//300的补码为:0000 0000 0000 0000 0000 0001 0010 1100
byte b=(byte)a;//因为byte只有1个字节将int强制转换过去会让int的少3个字节即24个bit位
//故将300的补码前面24个bit位去掉即可变成:0010 1100
情况2
int a=200;//200的补码是:0000 0000 0000 0000 0000 0000 1100 1000
byte b=(byte)a;//强制转换去掉前面的8*3=24个比特位
//变成了 1100 1000
//都知道无论什么码,第一个都表示符号位:故200强制啊转换变成了1 100 1000这个转成十进制是-56
位运算符号
符号 | 说明 | 解释 |
---|---|---|
& | 按位与 | 俩个都为1结果才为1,否者为0 |
| | 按位或 | 俩个有一个为1结果才为1,否则为0 |
^ | 按位异或 | 俩个不相同才为1,否者为0 |
~ | 按位取反 | 0变成1,1变成0 |
<< | 按位左移 | 向左移动,低位补0 |
>> | 按位右移 | 向右移动,高位补0或1(根据正负号确定) |
>>> | 逻辑右移,也叫无符号右移 | 低位溢出,高位补0 |
示例
按位与
-
2&3
2 的补码 00000000 00000000 00000000 00000010
3 的补码 00000000 00000000 00000000 00000011
运算结果 00000000 00000000 00000000 00000010
十进制结果 2
按位与 & 的运算规则就是:二进制位中,如果俩个都是1结果就是1要不然就是0
按位或
-
200 | 10
200的补码:0000 0000 0000 0000 0000 0000 1100 1000
10的补码: 0000 0000 0000 0000 0000 0000 0000 1010
计算结果: 0000 0000 0000 0000 0000 0000 1100 1010
十进制结果是:202
按位或 | 的运算规则就是:二进制位中,俩个中只有一个1结果才为1,要不然就是0
按位异或
-
2^3
2 的补码 00000000 00000000 00000000 00000010
3 的补码 00000000 00000000 00000000 00000011运算结果 00000000 00000000 00000000 00000001
十进制结果是:1
按位异或 ^ 的规则就是:二进制位中,两位一个为0一个为1,结果为1,否则为0
按位取反
- ~-2
-2 的补码 11111111 11111111 11111111 11111110
运算结果 00000000 00000000 00000000 00000001
结果的原码 00000000 00000000 00000000 00000001
十进制结果 1
按位取反 ~ 的运算规则位:将数据的0变成1,1变成0即可
左移
-
200<<2
下图为200的补码
将200左移俩次
将空出的位置补补上0
消除左移超出部分的0
故得到200左移2位的补码数
这个数转为十进制为800
左移计算公式:左移一次,原数据*2
右移
- 200 >> 2
200的补码为:
同理将200的补码向左移动2位
不难看出此时右边多出了2位,将最左边是符号位,根据左移的是正数还是负数来确定补0或1,其他多出部分直接补0即可
可得到:
同理左移就是,左移一次:要移动数据/2
无符号右移
无符号右移和右移动的区别就是:
最左边空出的高位符号位不需要管原数据是正还是负直接添0即可
标签:0000,--,补码,1111,00000000,源码,java,原码,1000 From: https://www.cnblogs.com/wdadwa/p/java_learning_0.html