40

深入理解计算机系统cp2:定点数的表示和运算

 4 years ago
source link: https://www.tuicool.com/articles/rEjqeyF
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

EvyEBnE.jpg!web深入理解计算机系统cp1:存储单位、数制、编码 中解释了字符编码,我们知道了计算机是怎么把字符转化为二进制的;本文将解释数字编码,介绍计算机如何把数字转化为二进制,以及相关的运算问题。

1.定点数的表示

1.1 无符号数

  • 定义:无符号数就是没有体现正负号的数(这意味着所有的无符号数实际上都是正数),整个机器字长的全部二进制位均为数值位,没有符号位。以 108D 为例,它对应的二进制数是 1101100 ,这实际上也就是它的无符号数,可以看到所有的位都是数值位。
  • 表示范围:以八位二进制数为准,范围就是 0000000011111111 ,也就是 0 到 255

1.2 有符号数

  • 定义:有符号数就是有体现正负号的数,整个机器字长的全部二进制位中,最高位作为符号位,0 表示正数,1 表示负数,其余位则是数值位。依然以 108D 为例,它对应的二进制数是 1101100 ,而对应的有符号数则要在最前面加上符号位 0,即它的有符号数是 01101100 .

  • 表示范围:以八位二进制数为准,范围应该是从负数到正数,即从 1111111101111111 ,也就是 -127 到 127

1.2.1.真值和机器数

  • 真值:就是带有正负号的实际十进制数,比如上面例子中, +108D 就是真值
  • 机器数:机器数就是一个数在计算机中的二进制表示形式,注意 机器数是由符号位和数值位 构成的,比如上面例子中, 01101100 就是机器数。

-156D (真值)= 110011100B (机器数)

1.2.2.原码、反码、补码和移码

(1)原码表示法

7viAZnz.png!web

简单点理解,原码就是符号位加上真值(二进制)的绝对值,同时用逗号将符号位和数值位隔开。比如,+1 就是 0,0000001 ,-1 就是 1,0000001

原码的特点是简单、直观,但是原码在进行加法运算的时候会出现问题。正数加正数或者负数加负数是正常的,但是正数加负数就会出错。比如我们现在想要计算 -1+3,我们心想:-1 是 10000001 ,+3 是 00000011 ,加起来得到的是 10000100 ,所以结果是 -4,但 -1+3 应该是等于 2,所以这个结果是错的。我们发现,本来应该做的是加法运算,但实际上变成了减法运算(-1-3=-4)。

我们首先想到,可以通过将“正数加负数”转化为“正数减正数”来手动纠正这个错误。上面的例子就变成 0000001100000001 ,结果是 00000010 ,也就是 2,这个结果是正确的。

但是每次都这样手动转化,计算起来还是太麻烦了。于是我们接着想:有没有一种方法,可以让“正数加负数”中的 负数等价于一个正数 ,从而确保始终进行的是相加操作呢?

于是这时候就引出了补码的概念。

(2)补码表示法

  • 补数和模:理解补码之前,我们先来理解两个概念: 补数

    拿时钟举例,想要从10点拨到8点,有两种做法,一种是逆时针拨2个单位,记作-2;一种是顺时针拨10个单位,记作+10,这两种操作是等效的(有点 负数等价于一个正数 的意思)。这时候我们就说,-2 是 +10 以 12 为模的补数,记作 -2≡+10(mod 12) ,同理,-5 相当于 +7,-4 相当于 +8。

  • 那么怎么基于补数和模的概念将“正数加负数”转化为“正数加正数” —— 即怎么令 负数等价于一个正数 呢?假设我们现在有一个寄存器可以存放四位二进制数(此时,模为16),我们想要让 1011 变成 0000 ,最容易想到的办法就是 1011-1011=0000 ,注意这里是正数加负数。想要变成正数加正数,就要找到等价于 -1011 的正数, -1011 就是 -11,-11 以 16 为模的补数就是 +5,+5 就是 +0101 ,这个正是我们要找的那个等价正数,因此这时候, 1011-1011 变成了 1011+0101 ,其结果是 10000 ,不要忘了寄存器只能存放四位,所以结果其实是 0000 ,恰好与我们“正数加负数”时得到的结果无异。

  • 接着引入补码的概念:

    • 对于正数:正数的补码和原码相同;
    • 对于负数:负数的补码等于其原码在保持符号位不变的情况下,其余各位取反,末位加一(取反加一)。 注意 ,补码的补码等于原码,这可以用来根据补码求原码。
    • 也可以用下图方法计算补码:
      u6FbEri.png!web

还是上面的例子, 1011-1011 ,也就是11-11,我们考虑+11和-11,+11的原码=补码= 01011 ,-11的原码是 11011 ,因此补码是 10101 ,那么 01011+10101 就会等于 100000 ,因为寄存器是五位的,把前面的1去掉,那么结果就是 00000 ,也就是0,和上面的运算结果一致。

(3)反码表示法

IFZ3AjU.png!web

反码很好理解:

  • 正数:反码等于原码等于补码;
  • 负数:反码等于原码保持符号位不变的情况下其余各位取反。也就是说,补码=反码+1
  • 反码的反码等于原码,这可以用来根据反码求原码。

(3)移码表示法

AJJRraI.png!web

补码存在的问题是,仅从补码本身来看,很难比较两个数的大小,为此引入了移码的概念。移码指的是在真值(二进制)的基础上加上一个偏移量,通常这个偏移量是2^n。其中,n是数值位的位数。

例如,对于 -10101 ,其移码是 2^7+(-10101)=10000000+(010101)=0,1101011


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK