在上篇博文(点击查看)中,做而论道检验了用无符号数和原码利用加减交替法做除法的正确性。 其实,也用不着检验,加减交替法,本来就是用无符号数推导出来的,其正确性毋庸置疑。 用原码来加减交替来做除法,仅仅是在前面添个 0 而已,也不会得出错误的结果。
本文打算在补码加减交替法中,再验证一组数据,然后,就总结一下吧。
先看一组数据:被除数X = 144、除数Y = 12。
X/Y应该是什么呢?
大家应该一眼就能看出结果:商Q = 12,余数R = 0。
做而论为什么选用这么简单的数据? 目的,就是想看看补码除法运算的【商末位恒置一】,能弄出什么样的结果。 此时的商,本应是偶数,末位置一后,还能正确吗?
下图是由人工计算无符号数相除求 X/Y 的计算过程。
用二进制数来做除法时,被除数X的位数,最好是除数Y位数的二倍,这样得出的商Q的位数,也就和除数Y的位数相同了。 本题目中X的位数是 8,Y、Q、R的位数,都是 4。
由图可见,用人工进行二进制数的除法(见上图左下角),还是很简单的,不过就是:移位、相减、移位、相减 ... 而已,如果不够减就不减了。 但是,用加减交替法来做除法(见上图右方),就麻烦多了。
在进行加减交替计算时,做而论道没有采用早已过时的补码来运算,而是直接采用了加减除数Y的算法。 这是因为当前的计算机中,并不是仅仅含有加法器了,而是早就有了算术逻辑单元 ALU 了(点击查看),它来做减法,那是相当方便的。
用 ALU 做加法时,ALU 将在进/借位端,输出进位的值。用 ALU 做减法时,ALU 将在进/借位端,输出借位的值。 如果够减,进/借位端将输出一个 0;如果不够减,进/借位端将输出一个 1。 本题目中,共进行了 4 次加减运算,进/借位端输出的数值可见上图括号中的内容(0011)。 由此,就得出了 4 位的商:1100。
在得到预定位数的商之后,如果进/借位端还输出 1,则需再进行一次加Y来 “恢复余数”。
在本题目中,共有 4 次移位、4 次加减法、得到了 4 位的商。 另有一次加法是恢复余数。
经过上述的计算,可以验证用无符号数加减交替法做除法,结果是正确无误的。
下面看看用原码的加减交替法来做除法吧。
原码加减交替做除法的步骤如下。
(1)符号位和数值位分别计算:
商Q的符号位由被除数和除数的符号通过异或运算获得。
商Q的数值位由被除数和除数的绝对值相除计算获得。
余数R的符号,与被除数X的符号相同。
(2)进行运算时,被除数和除数均由绝对值的补码参加运算。
(3)除法的第一步是做减法,即:余数R=被除数X-除数Y。
之后的运算,则要加减交替:
若余数R为正,下一步就是减去除数Y;
若余数R为负,下一步则是加上除数Y。
(4)上商的原则:
若余数R为正,则商 1;
若余数R为负,则商 0。
(5)移位:
上商后,再将余数R进行逻辑左移一位。
(6)加减的次数为 n+1,即可求得 n+1 的商。
但是若此时的余数R为负,则要恢复余数(无需移位)。
此处的 n,是绝对值的位数,+1,则是增加一个符号位。
由上述步骤可知,参加运算的数值是X、Y的绝对值。 绝对值,当然都是正数,写成原码,就是在绝对值前面,添上一个符号位 0。 这就比无符号数的运算,多用了一个二进制位。 那么,同样规模的运算器,所能计算的数值范围,就只有无符号数的一半了。 另外,虽然添上了一个符号位 (0),但是,也只能求得商的绝对值,商的符号位还需要另外用异或门来算。 添上了一个符号位,其用途,仅仅是用余数R的符号用来判断R的正负。 其实,这是多余的。用 ALU 输出的进/借位,同样可以判断R的正负。
另外,由于原码运算中的商,要比无符号数多一位符号位,因此,就必须比无符号数除法多做一次加减运算。
由此看来,用原码加减交替法来做除法,就是平白无故的增加了一个无用符号位。 用原码来做除法,并无任何可取之处。 只是让计算机老师用来赚取讲课费而已了。
因此,做而论道也就不打算用原码加减交替法再做一遍 144 / 12 了,没有意思。 下图,只是的网上随便找来的一个例题。
这张图,也是来自某个著名考研辅导材料中的插图。 做而论道仅仅是调整了一下各个字符的位置,以显得紧凑一些。 原图的网址是:点击查看、点击查看、点击查看、点击查看。
由图可见,参加运算的数字都是补码。这种方法,却叫做原码除法,名不副实啊。
另外,参加运算的数字X、Y都是小数,这也不符合计算机中的事实。 在计算机中,只有 0 和 1,根本就没有小数点,这是大家都知道的。 无论人类想要处理什么形式的数字(整数小数浮点数)、什么样的信息(英文汉字声音图像控制符 ...),放在计算机中,都必须是用整数的运算来解决问题。 作为《计算机组成原理》,却不用计算机本身的属性来讲解,这是干什么? 匪夷所思。。。
再者说,把小数点都右移 4 位,值不变,这种小学的知识,计算机专家不会不知道吧?
所以,就有:X / Y = 0.1011 / 0.1101 = 1011 / 1101。
再转换到十进制,就是:X / Y = 1011 / 1101 = 11 / 13,余 0。
所以,商Q = 11/13、余数R = 0,这才是图中数据相除的正确结果。
那么,图中的计算结果,为什么不是正确的结果呢?
其原因是:计算机专家偷偷的加入了 4 个 0,导致被除数X已经变了。
由图可见,在运算过程中,共有 4 次左移,在右边添上了 4 个 0。
0 ! 即使是 0,也不是可以随便填写的。
你写上了 0,它就要参加运算!
那么,上图中的除法,就不是题目给定的:1011 / 1101 了。
而是:1011 0000 / 1101 了。
换算到十进制,就是:176 / 13 = 13,余 7。 二进制则是:1101,余 0111。
图中的结果:商Q = +0.1101、余数R = 0.0000 0111。
这结果,虽然不对,但是也有点贴边了。
究竟差在什么地方呢?
做而论道已经没有兴趣帮这些专家圆谎了。
下面看看补码加减交替做除法吧。
就算一个:-144 / - 12 = +12,余 0, 好不好?
用二进制来写,就是:-1001 0000 / -1100 = +1100,余 0000。
如果光看绝对值,它们就是前面无符号数除法的数值。
用补码加减交替来做除法,据说是可以一次性求出商Q的符号位和数值位。
先做一些必要的转换,如下。
做而论道没有使用双符号位,其原因是:题目规定字长为 5 位(仅含 1 位符号位),如果使用双符号位,就不符合题目要求了。 做而论道也没有使用小数,这是因为在计算机中,并没有小数点。 另外,补码中的符号位和数值位,是可以连在一起写的,但是为了和计算机专家常用的格式相符,就用了下划线来分开。
数据准备好了,就可以计算了。补码加减交替做除法的步骤如下所示。
虽然,做而论道既没有使用双符号位、也没有使用小数,但是相减相加、上商、逻辑左移一位,都是按照规定的方法进行的。可是,经过运算,结果却非常不理想!
私下,做而论道也用双符号位算过,运算结果也和上图相同,明显是错误的。
此外,做而论道也用 ALU 的算法做过。 在相减运算时,直接用 [ X ]补 来相减,而不是用 [-X ]补 相加。 结果,依然与上图中的错误结果相同。
怪不得计算机专家热衷于使用小数来计算。 使用小数来计算,即使算出的结果是错误的,你也无法验算。 但是,翻遍了整本书,都是讲小数的算法,那么,整数的除法运算(如-144 / -12),又应该怎样计算呢? 没找到。
经过上述的验证,做而论道有一个小结如下。
1. 用无符号数加减交替做除法,虽然商的符号和绝对值需要分别求解,但是,这种算法,数值的范围较大。 因此,还是值得推荐使用的。
2. 用原码加减交替做除法,商的符号和绝对值也是需要分别计算的。 但是原码的符号位,要占用一个位,所以绝对值的范围,仅是无符号数加减交替法的一半。 如果想让数据范围达到无符号数的范围,运算器就必须多一个位。 同时,因为商也多了一位,因此加减的次数,也得多算一次。 故此,不推荐使用。
3. 用补码加减交替做除法,虽然号称可以一次性算出商的符号和绝对值。 但是,其错误结果却是惨不忍睹。 能用不能用呢? 还是别提了吧。 就留着让计算机老师赚点讲课费吧。
另外,任何计算机,都不可能在 CPU 中集成安装两种或三种除法器。 应该有一个,就足够用了。 那么,在教学过程中讲了三种除法方案,只有一个是有用的,另外两种就是无用的垃圾知识。 这种教学方法的效率,也太低了吧! 好不容易上一回大学,却学了三分之二的垃圾,悲哀!
个人看法而已,如有不当之处,欢迎诸位网友点评。
另外,所谓的 “恢复余数、不恢复余数”,都是不存在的伪命题。 因为,“不够减的余数”,在硬件电路中根本就不会出现。 因此,要做除法,只管进行:相减、移位、相减、移位 ...,就可以了。 那么,所谓的加减交替法,也就没有什么意义了。
按照这种思路,做而论道分别采用循环结构和减法阵列结构,设计出了两种无符号数除法电路,可见做而论道以前写的博文:点击查看、点击查看。 经过仿真运行,这两种电路,都是可以正常工作的。 感兴趣的网友,可以仿照该电路,自己进行实验。
--本文完--