之前讨论的都是正数(无符号数)。负数(有符号数)该怎么表示呢?
有符号数表示方式(负数)
用正负号对数字进行编码:
- 0:表示正号
- 1:表示负号
正负号放在数的最前面,也就是二进制数的最高位。
+5:5转换成二进制数就是101,凑够8位的话就是00000101,最前边D7位是0,表示正号
-5:5转换成二进制数就是101,凑够8位的话就是10000101,最前边D7位是1,表示负号
-10:10转换成二进制数就是1010,凑够8位的话就是10001010,最前边D7位是1,表示负号
问题:
直接这样表示会有问题,如果带了负号,最后几个数相加结果可能是错误的。
比如5+(-10),应该等于-5。但是分别将其转化成二进制计算:
00000101 + 10001010 = 10001111(也就是-15)
为了保证负数计算的正确性,所以出现了补码的概念。
补码
补码的基本思想:
把负数表示成加几等于0的形式
比如,一个数x,若x+5=0,则x = -5
“补码”:补上几就会变成0
补码与原码互相转化的公式
原码转化成补码的计算公式:
补码还原成原码的计算公式:
注意:
符号位:就是D7位(最高位,又是最左侧的那一位)
取反:0变成1、1变成0
怎么通过补码计算一个带负数的加法?
1、将一个十进制数转换成二进制,得到原码
![image.png](https://cdn.nlark.com/yuque/0/2021/png/269022/1615715756944-278475db-f0a1-4cd7-a1b4-f69210067ea4.png#align=left&display=inline&height=36&margin=%5Bobject%20Object%5D&name=image.png&originHeight=72&originWidth=634&size=33392&status=done&style=none&width=317)
2、把原码除符号位以外的所有位全部取反
符号位:就是D7位(最高位,又是最左侧的那一位)
取反:0变成1、1变成0
3、把反码加1,构成补码
4、然后在进行加法运算
![image.png](https://cdn.nlark.com/yuque/0/2021/png/269022/1615716015535-eafdc66a-cbc8-4ef2-8570-db4be3210f5c.png#align=left&display=inline&height=109&margin=%5Bobject%20Object%5D&name=image.png&originHeight=218&originWidth=736&size=91455&status=done&style=none&width=368)
5、最后将得到的补码加法结果再取反加一(除去最高位),得到原码如下
(负数在计算机中都是以补码的形式存在的,所以要看真实值,需要取反会原值)
原码
反码
补码
补码例子
八个1表示的值是多少?
(11111111B,这种最高位1开头的说明是负数,在计算机中负数使用补码表示,所以这是一个二进制的补码)
1、可以用取反加1还原成原码,再转成十进制查看。
2、可以利用补码的定义直接进行推算:
补码:是把一个负数写成加几会变成零的形式。如果一个负数是-5,那么+5会变成0
我们观察下上边的数加几会变成0?
D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
+1 | ||||||||
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
溢出、去掉 |
用八位数表示一个字节,加1后得到九位,最前边1超出了1个字节的表示范围(8位,超出一位)属于溢出,溢出的值会被舍去。
因为这个数加1等于0,所以他一定是-1
例子2
如果用一个字节表示有符号数,那么其取值范围应该是从几到几呢?
如果是正数:
- 最高位为0,取值范围就是00000000 - 01111111,(从0开头,后边跟七个0~七个1)
就是0 ~ 127(1后边七个0表示128,0后边七个1等于1后边七个0-1,也就是128-1)
如果数符为负