405-除法的运算过程
# 405-除法的运算过程
在加、减、乘、除这样的基本算数运算当中, 除法是最为复杂的。因此,我们想要实现硬件的除法器, 还是从最简单的情况开始说起。
我们还是采用模仿纸笔进行除法运算的方式,来回顾一下除法的运算过程。 这里是两个十进制的数, 被除数是 1001010, 除数是 1000, 这是两个经过精心挑选的数,用它们进行除法运算, 运算的过程中只会出现 0 或者 1, 所以看上出又像是二进制表示的数。所以我们通过这个例子可以看出十进制的除法运算,和二进制的除法运算之间的联系。 这个运算的过程,我们已经非常熟悉了,所以我们快速地来看一遍。
首先将除数和被除数,从高位开始对齐,然后将对齐的这部分进行一个减法, 当我们发现减完的结果是一个正数,也就是所谓的够减的时候,我们就在上面标一个 1, 然后把减完的差放在下面,
再从被除数后面的位拿一个数下来, 这时候我们用眼睛看一看就可以发现,现在这个数还不够去减这个除数,所以我们在上面标一个 0, 然后再多拿一位,
还不够,那么我们在最上面再标一个 0,然后再拿一位下来, 现在我们发现,这时候已经够减这个除数了。
好,那我们在这上面标一个 1,然后把除数写在这里, 再执行一次减法,减完的结果已经比除数小了,而且 被除数那里也没有多余的位可以拿下来继续运算,这样我们这个除法就已经完成了。
先得到最上面的这个数,就是这个除法运算的商, 而最下面的这个数,我们称为余数。
如果用一个式子来表达这四个数的关系,那就是被除数,等于商乘以 除数,再加上余数。当然我在描述这个除法运算的时候,非常的口语化, 而且也有人的智力因素参与其中,比如说用眼睛看一看够不够减,之类的。 这样的描述过程是很难用硬件去实现的。 想要设计一个硬件的除法器,首先我们要从硬件实现的 角度出发,来考虑如何描述除法的运算过程。
那我们用这样的方式再来看另一个例子。 这里就是两个二进制数的除法了,被除数是 00000111,这就是十进制的 7, 而除数是 0010,这就是十进制的 2, 所以这就是做 7 除以 2。 对于硬件实现,我们首先要考虑的,是这个运算的操作数的宽度。 这里我们可以看到,被除数是一个 8 位宽的数,而除数是一个 4 位宽的数, 因此在这样的情况下,即使高位是 0,我们也不能将这个 0 省略,因为它们实实在在地,在硬件中占据了一个位置。
很显然,我们可以把被除数放在一个 8 位宽的寄存器当中, 同时我们还要注意,被除数是在不断的和除数进行减法的操作。 在经过几轮之后,减法的运算结果最后就产生了余数。 所以,如果我们将每次减法运算的结果都放回到被除数的寄存器当中, 那么这个寄存器又可以被称为余数寄存器。 现在我们就有了第一个部件,就是一个 8 位宽的余数寄存器。 然后我们还需要一个部件来保存除数, 还需要一个部件来保存商。
那我们在纸上进行除法运算的时候, 第 1 步,会把除数抄写到这里, 并将被除数当中最高的四位和这个除数进行对比。 经过比较,我们发现被除数的这一部分是比除数小的, 所以不能执行这个减法。
因此,我们在于当前除数最低位对齐的这个地方, 标上我们得到的第一位的商,也就是 0,目前执行的这个过程, 我们就称为第一轮。
然后我们会怎么做? 我们接下来要做的就是往右挪一个位置,把除数再抄一遍。 好,我们把除数抄在这里,如果我们忽略这些数字底下衬着的这些带颜色 的框,那它实际上和在纸上进行除法运算我们所写的内容是一样的。 而如果我们带上了这个写了除数的长条形的方框,那我们又可以发现 这个除数 0010 好像是在这个方框中右移了一位, 这样我们就可以考虑在硬件上用一个带右移的寄存器来实现这个功能。 那么这个时候,又需要用被除数和除数进行一个减法运算了。 那现在够不够减呢? 实际上还是不够的。其实我们不用去找应该对其哪几位进行减法的比较, 如果我们直接把这个写的除数的长条方框看成一个 8 位的寄存器的话, 那就可以把其中没有标明数字的地方都看做是 0,每次都是把这个标着除数的 8 位的寄存器的内容和上面标着余数的 8 位寄存器的内容进行比较, 那么现在这个除数还是更大一些,所以这一轮也不能执行减法,这样我们在商这个位置再标一个 0。
我们要注意,在纸上运算时,我们直接就写上了第二个 0, 而现在,我们在硬件上只给商预留了四个位置,也就是说, 是一个四位的寄存器。所以这个操作就好比将商的这个寄存器 往左进行了一个移位,并在最右端补入了一个 0, 那这就是第二轮。
然后我们继续,再将除数往右边挪一位, 再和被除数进行比较,现在还是除数更大,所以这一次还是不能执行减法,而商再写上一个 0, 这就是第三轮。
我们再看下一轮,再向右移一位除数之后, 我们发现现在被除数更大了,可以执行一次减法了, 减完的结果就是 00000011。 因为执行了一次减法,所以我们在商对应的位置标上了 1, 也就相当于对于这个商的寄存器往左移动之后,在最右端补上了一个 1, 然后我们把这个减法的结果更新到余数寄存器当中去, 这就是第四轮。
但现在还没有结束,我们还需要 把除数再往右移一位,并和当前的余数进行比较, 我们发现还可以进行一次减法运算, 所以在最上面,我们再把商从最右边移入一个 1, 然后再回来看下边,我们再执行一次减法,得到了一个结果为 1, 并把这个结果再更新到余数寄存器当中去, 这就是第五轮。
现在我们就已经得到了最终的结果, 最上面是商的最终结果:0011, 最下面是余数的最终结果,也就是 1。 0011 是十进制的 3,所以 7 除以 2,商为 3,余数为 1, 这样的结果显然是正确的。
我们再来整理一下这个例子。 对于被除数,我们选择的是十进制的 7,对于二进制,它可以用 8 个比特来表示, 而且被除数我们可以视为初始化时候的余数。除数是 2,我们用 4 个比特的寄存器来保存, 而且在运算的过程中,我们可以看作将除数不断地右移,并和被除数进行相减。 对于余数,虽然它最终的结果很小,但是因为它可以与被除数共享一个寄存器, 所以我们也用 8 个比特来表示。 对于商,在这个例子中是 3,我们要注意到的是,在运算过程中,它的每一个比特是从高到低,也就是从左往右依次生成的,可以视为不断地左移而形成, 在这里我们也用 4 个比特的寄存器来保存。
我们要注意,这个位宽和乘法运算正好是相反的, 在乘法当中,我们一般会约定乘数和被乘数的宽度是一样的,如果两个都是 4 位宽的,则乘积最多为 8 位宽, 所以在除法当中,我们也用了类似的约定。 如果被除数是 8 位宽,则除数和商都约定为 4 位宽。 现在我们就有了一个适合硬件实现的除法运算过程了。
从这个事例我们就能够看出,除法运算确实是非常复杂。 不过现在我们应该很有信心, 只要我们能够用适合硬件的方式把这个运算过程描述出来, 我们就应该能够把这个除法器设计出来。
peterjxl 小结:就是用被除数不断的减去除数,将除法变为减法
- 01
- 中国网络防火长城简史 转载10-12
- 03
- 公告:博客近期 RSS 相关问题10-02