本文讲什么?
在计算机中,小数点并没有用专门的器件去表示,而是按照一种约定的方式,统一存储在寄存器单元中的。算数逻辑运算单元(ALU)是CPU的组成部分,负责算数和逻辑的运算。那么,ALU究竟是如何工作的呢?
这就是本文主要探讨的内容:
- 什么是定点数?
- 定点数的位移、加、减、乘、除运算是如何进行的?
定点数是啥?
从字面意思来理解,“定点数”就是“点”不动的数。那么究竟是什么“点”不动呢?没错,就是“小数点”。
在上一讲我们说道,不论是整数还是小数,都是有小数点的。整数的小数点表示在最后一位数字的后面,而小数的小数点标识在真值的符号位后面。如图所示:
除了定点数,还有一种数叫做“浮点数”,浮点数将在下一讲展开介绍。
定点数的运算
好了,介绍完定点数的基本概念以后,我们展开讲定点数的位移运算和四则运算。定点数的四则运算实际上要比我们想象的复杂的多。
机器并不像人,一眼就知道二二得四,他需要知道2的定点表示形式,然后两个定点数相乘,相乘是有一定的过程的,经过了这个过程,才能得到结果的二进制数,最终输出给我们。我们要做的,就是了解加减乘除究竟经历了什么样子的过程。
定点数的位移运算
不要看移位运算简单,但是它在计算机的运算中的地位是举足轻重的。没有移位运算,也就没有后面的乘除法,乘除法就是在移位运算和加减运算的配合下实现的。
移位运算的规则:虽然正数和负数的移位运算规则不相同,但是相同之处在于移位后正数和负数的符号不变。那么规则就变成了移位运算时,符号位不动,数值位按照如下规则进行移位。
举个例子:
将+26的原码、补码和反码分别左移一位
结果是:[26]原 = [26]反 = [26]补 = 0,0011010,根据规则,原码、反码、补码左移一位的结果是:0,010100将-26的原码、反码、补码分别左移一位
[-26]原 = 1,0011010,左移一位:1,0110100
[-26]反 = 1,1100101,左移一位:1,1001011
[-26]补 = 1,1100110,左移一位:1,100110
移位的运算是不是很简单?只需要根据规则来就可以了。重点在下面的几种运算中。
定点数的加法与及减法
定点数的加减运算只需要记住一个原则:加法直接加,减法先变为加法后再计算。
什么意思呢?比如[A+B]补 = [A+B]补,[A-B]补 = [A]补 + [-B]补。
来看两个例子:
A = -1001,B = -0101,求[A+B]补
[A+B]补 = [A]补 + [B]补,[A]补 = 1,0111,[B]补 = 1,1011,所以最终的结果是:11,0010,但是这并非我们的最终结果,最终结果应该丢掉第一个1,即1,0010.为什么呢?这涉及到一个模2运算的问题,如果不想深究只需要记住,一个数只能有一个符号位不是吗?A = -1001,B=-0101.求[A-B]补
[A-B]补 = [A]补 + [-B]补,[A]补=1,0111,[-B]补=0,0101(求法:[-B]补等于[B]补符号位和各位取反,末位加一),这样得到最终的结果,丢弃掉多余的位即可。
溢出的判断:如果计算机的机器字长为4,那么能够表示的真值范围在-8~+7之间,如果两个数相加减,跳出了这个范围,则为溢出。
那么应当如何判断溢出呢?
原则:
- 不论加法还是减法,只要实际参与运算的两个数的符号相同,但是与最终的结果的符号相反,则为溢出。比如我们的第一个例子,两个参与运算的数的符号相同,且和最终结果的符号也相同,则这种情况就不是溢出。
- 最终结果的两位符号位如果相同,则无溢出,如果不同则溢出,还是第一个例子,计算后的结果是11,0010,两位符号位相同,没有溢出。
定点数的乘法
乘法的运算方式形成过程,我推荐大家看看计算机专业的教材,即唐朔飞老师的《计算机组成原理》。本文奔着实用性的角度,不会过度发掘计算方法的推导过程,因为我的解释并不如教材上的好。至于真正的计算,不能说是优于教材,最起码你你能够快速上手计算,如果你做到了,那么我的目的也就达到了。
定点数乘法的计算方式:
原码一位乘
- 说明:有A*B,令初始部分积为0,分别取A、B的绝对值A’、B’。乘数为B’,取乘数最后一位,如果是0,则部分积加0;如果是1,则部分积加A’。加法操作执行完成后,部分积右移一位,继续执行上述操作,直到原有乘数的所有位均被用完。最后一步的加法执行完成后,右移一位,形成最终结果。最终结果的正负由二者的符号的异或决定。
单纯的说你可能会有点懵逼,我们来结合一个实际的例子看看。 - 例:A = 0.1101,B = 0.1011,求A*B。
为了方便,我们将上述的计算过程放入表格中进行计算,表格如下:
乘数一栏的上部分数字暂时不用管,仔细看一下运算步骤,和我总结的对比,仔细体会即可。
- 说明:有A*B,令初始部分积为0,分别取A、B的绝对值A’、B’。乘数为B’,取乘数最后一位,如果是0,则部分积加0;如果是1,则部分积加A’。加法操作执行完成后,部分积右移一位,继续执行上述操作,直到原有乘数的所有位均被用完。最后一步的加法执行完成后,右移一位,形成最终结果。最终结果的正负由二者的符号的异或决定。
原码两位乘:原码两位乘有运算规则,和一位乘有着类似的地方,但是不尽相同。原码两位乘是用两位乘数的部分来决定新的部分如何形成的运算方式。两个二进制数共有四种形态:00,01,10,11,可以表示不同的移位方式以及加法的方式(下面会看到)。再加上一位标志位C,就能实现更加复杂的操作。如图所示:
有了上面的规则,就能够很轻易的根据原码一位乘做出原码两位乘,计算过程:初始化部分积为0,写入乘数,标志位置为0.判断乘数的后两位以及标志位满足何种关系,调用相应的方法移位并设置标志位,最后的结果向右移动两位,根据x和y的符号的异或确定符号。有必要说明的是,两位乘需预留出3位符号位。给出个例子:- 例子:设x=0.111111,y=-0.111001,用原码两位乘求出[x*y]原
这样就非常容易理解了。
- 例子:设x=0.111111,y=-0.111001,用原码两位乘求出[x*y]原
补码乘法:补码一位乘与原码一位乘类似,区别在于,当乘数为正时,补码乘法运算方法与原码一位乘运算方式相同;当乘数为负数时,补码一位乘前半部分同样和原码一位乘相同,不同之处是在运算完成后,需要把最终结果加上[-x]补用于校验,才能得到最终的结果。这部分的推导同样可以参见教科书。下面给出一个例子:
- 例子:[x]补 = 0.1101,[y]补 = 1.0101,求[x*y]补。由于[y]补为负数则需要在最终的结果加上[-x]补用于校验。
- 例子:[x]补 = 0.1101,[y]补 = 1.0101,求[x*y]补。由于[y]补为负数则需要在最终的结果加上[-x]补用于校验。
补码比较法:相信有了前面的基础,直接给出规则你就能够解决问题了,补码比较法的运算规则如下:
给出例子:[x]补 = 0.1101,[y]补 = 0.1011.运算过程如下:
补码两位乘:补码两位乘和上面的方式没有太多的区别,主要就是两位乘采用三位符号位,三位判断位(乘数的位),有了运算规则,做出题目简直太简单了。
例子:[x]补=0.0101,[y]补=1.0101,求[x*y]补。
定点数的除法
这篇文章的内容已经比较多了,为了方便读者消化知识,除法的讲解放在下一篇文章中,敬请期待。
结语
如果你喜欢我的文章,请关注我的微信公众号“最高权限比特流”吧!
【参考文献】《计算机组成原理》,唐朔飞。
来源:https://www.cnblogs.com/roobtyan/p/9576678.html