跳至正文
View Categories

< 1 min read

主要内容 #

减法运算的不同之处 #

上节课中,我们讲了加法的运算过程,大家是否好奇,减法是怎么处理呢?是不是和加法一样呢?

现在,基于大家现在掌握的知识,我们可以正式谈一谈,负数(减法)要怎么处理。

大家可以先思考一下,假如你就是计算机,你会怎么处理下面的运算呢?

十进制数:
10  -   1  =  9
   ||
   ||
   \/
二进制数:
?????

减法运算推导 #

在计算机中,我们其实是这样处理的

十进制数:
10  -   1  =  9
   ||
   ||
   \/
十进制数:
10  +  -1  =  9
   ||
   ||
   \/
二进制数:
1010 + (负的0001)= 1001

大家可以想一想,(负的0001)应该是多少呢?还记得我们讲过的“符号位”吗?

二进制数:
1010 + (负的0001)= 1001

 0000 1010  +  (1000 0001)  // char
=1000 1011
= -11(10进制) =/= 9(10进制)

怎么不对呢?

负数在内存中的确是 (1000 0001) ,其实问题出在加法的计算过程中。

  • C++ 中,正负数直接相加的结果,并不能得到正确的减法结果。这是因为“符号位1”是人为约定的,不符合一般的数学运算规则。

我们来推导一下,到底需要怎么计算。

二进制数:
1010 + (负的0001)= 1001
1010 + X = 1001

假定,使用 char 类型,那么内存大小就是 8 bits

X = 0000 1001 - 0000 1010
X = 1 0000 1001 - 0000 1010  // 被减数 借位 

    1 0000 1001 
  - 0 0000 1010
-----------------
X = 0 1111 1111

X 最后保留 char 的 8 bits
X = 1111 1111

诶!出来了一个很奇怪的数据,不是吗?

小结 #

上述的运算,最终是这样进行的

十进制数:
10  -   1  =  9
10  +  -1  =  9

二进制数, char 类型:
 0000 1010 + (1111 1111)  // 【最关键步骤,称为“转化成补码”】

    0000 1010 
+   1111 1111
-----------------
= 1 0000 1001
  仅仅保留最低 8 bits
= 0000 1001 = 9(10进制)

补码 #

所谓“码”,就是内存中的那个二进制值。
所以,上一节中的“原码”,就是表示数值在内存中的那个二进制。

所谓“补码”,就是专门用于“减法计算中”,负数的表示。

  • 注意,“补码”,就是专门用于“减法计算”

怎么计算补码 #

原码为正数:
    补码 = 原码

原码为负数:
    补码 = 反码 + 1  // 反码见下面说明

原码为零:
    补码 = 0

反码 #

原码为正数:
    反码 = 原码

原码为负数:
    反码 = 原码的基础上, 符号位不变,其余各个位取反

所以,请特别注意减法的特殊处理。

习题 #

课后练习