之前讨论的都是正数(无符号数)。负数(有符号数)该怎么表示呢?

有符号数表示方式(负数)

用正负号对数字进行编码:

  • 0:表示正号
  • 1:表示负号

正负号放在数的最前面,也就是二进制数的最高位。
+5:5转换成二进制数就是101,凑够8位的话就是00000101,最前边D7位是0,表示正号
-5:5转换成二进制数就是101,凑够8位的话就是10000101,最前边D7位是1,表示负号

-10:10转换成二进制数就是1010,凑够8位的话就是10001010,最前边D7位是1,表示负号
image.png
问题:
直接这样表示会有问题,如果带了负号,最后几个数相加结果可能是错误的。
比如5+(-10),应该等于-5。但是分别将其转化成二进制计算:
00000101 + 10001010 = 10001111(也就是-15)
image.png
为了保证负数计算的正确性,所以出现了补码的概念。

补码

负数在计算机内部都是以补码形式存在的。

补码的基本思想:

把负数表示成加几等于0的形式
比如,一个数x,若x+5=0,则x = -5
“补码”:补上几就会变成0

补码与原码互相转化的公式

原码转化成补码的计算公式:

原码取反再加一(不包括最高位D7位)

补码还原成原码的计算公式:

补码减一再取反(不包括最高位D7位)

注意:

符号位:就是D7位(最高位,又是最左侧的那一位)
取反:0变成1、1变成0

怎么通过补码计算一个带负数的加法?

image.png

1、将一个十进制数转换成二进制,得到原码

  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
image.png

3、把反码加1,构成补码

101+1 = 110,如下
image.png
(前三步,得到一个数的补码)

4、然后在进行加法运算

  1. ![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、最后将得到的补码加法结果再取反加一(除去最高位),得到原码如下

(负数在计算机中都是以补码的形式存在的,所以要看真实值,需要取反会原值)
image.png

原码

一个数的二进制数。最高位为符号位,用0表示正号、1表示负号

反码

二进制数原码除符号位以外,全部按位取反。

补码

除最高位外,反码+1

补码例子

八个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
image.png

例子2

如果用一个字节表示有符号数,那么其取值范围应该是从几到几呢?

  • 如果是正数:

    • 最高位为0,取值范围就是00000000 - 01111111,(从0开头,后边跟七个0~七个1)
    • 就是0 ~ 127(1后边七个0表示128,0后边七个1等于1后边七个0-1,也就是128-1)

      image.png

  • 如果数符为负

    • 最高位为1,取值范围就是10000000 ~ 11111111,(从1开头,后边跟七个0~七个一)
    • 就是-128 ~ -1(1后边七个1就是-1)(1后边七个0,加上128等于0,所以这个数是-128)

      image.png
      结论:取值范围是-128 ~ +127,正好是2个值,256个值。

      总结:正负数的补码

      负数在计算机中都是以补码形式存在的,负数只有用补码形式才能正确计算。
      正数并没有补码这个概念,其原码、反码、补码是完全一样的,没有任何变化。
      image.png

      补码讨论题

      有一个数在计算机中存储为:11111111。如果按有符号数理解,它是-1;如果按无符号数理解,它是255。现在要将这个数参与计算,它到底是多少,该如何确定?