概述
乘法是我们日常生活中经常使用的运算。如果是两个非常简单的事物,我们用口算就能解决, 即使是比较大的数我们也只要用一支笔和一张纸就能够非常轻松的完成。这种方法我们在小学的时候就已经掌握了。那么计算机又是如何实现乘法的呢?这个问题就比较复杂了,不过今天我将用纸和笔这样最基本的工具,为大家来揭示计算机实现乘法的秘密。
那么我们就回到小学的时代来看一看如何用笔在纸上进行乘法的运算,我们要计算的这两个数是2345乘以9876。
首先我们要做的是最低位的乘法,5乘以6,那么5 * 6 = 30这还很简单,但其实这里隐含了一个复杂的操作,那就是去查九九乘法表。无论这个乘法表是牢记在了你的脑子里,还是藏在了你的口袋里,那么总之我们要进行查表,发现5和6对应的是30。所以把这个30拿过来,放在这里,我们写上0,标上进位3。
那么接着做下一步,下一步是4 * 6 = 24,我们就要加上这个进位的3得到27。在这里写上7并标上进位的2。
然后是3 * 6 = 18,标上了0,写上了进位2。
然后是2 * 6 = 12加上进位2是14,我们写上了4,然后进位是1。当然又没有更高位了,所以直接把这个1也写上。现在我们就得到了一个结果14070,然后很可惜这只是一个中间的结果,那么即使是这个中间的结果,我们也经过了四次查表运算,还进行了四次的加法,中间总共产生了四次的进位输出这么繁琐的一个过程。
而且同样的中间结果我们一共有四个,最后我们还要把这样的中间结果再加起来,才能得到我们最后的成绩。这样看来乘法的运算,实际上是非常繁琐的,那么我们能不能不要用这样繁琐的过程呢?可不可以有一些简单的方法能够更好的解决这样的问题?
想要找到简单的方法,我们不妨先来看一看简单的情况。我们找两个简单的数字,1000乘以1001,同时我们也把刚才用过的那张纸找回来放在一边作为一个参照,那么对于我们新选的这两个数字,我们同样也进行乘法的运算。方法是一样的,先拿乘数的最低位和被乘数的每一位进行相乘,那么0乘1还是0,1乘以1就是1,进行这样四次相乘以后得到了四个数1000,组成了我们第一个中间结果。
然后是乘数的第二位,也和被乘数的每一位相乘,从而得到了第二个中间结果。
然后是乘数的第三位,得到第三个中间结果。
最后是乘数的第四位和被乘数的每一位相乘之后得到最后一个中间结果。
我们再把这些中间结果加起来就得到了我们最后运算的乘积,也就是1001000,我们用普通的乘法运算的方法自然就可以完成这次乘法的运算,但是对于这个例子的特殊情况我们发现实际上它展示了一种更为简洁的过程。
在介绍这个过程之前我们先把几个名词确定下来。被乘数,乘数,最后的运算结果是乘积。
那么对于这个例子,每个中间结果是怎么生成的呢?原则其实可以很简单,我们不用再去关心九九乘法表是怎么样的,也不用再去关心每一位产生的进位是不是要加起来,我们只需要观察当前进行运算的乘数的位,如果这一位是1,那我们就直接将被乘数放置在与它对齐的位置上就可以了。
如果当前参与运算的乘数位为0,那我们则直接将零放置在与它对齐的位置上,这就是我们经过简化后的运算方法。
针对这样的特殊情况每一个中间结果的产生都不需要去查找乘法表,都不需要进行加法的运算,要么是被乘数本身;要么是全零,根据当前参与运算的乘数位做一个非常简单的二选一的操作就可以了。
那么对于十进制来说这只是一种非常特殊的情况,并没有普遍的意义,但是如果我们的运算当中只会出现1或0,那这就是一个通用的方法了。那很好,二进制正好符合这个特点,所以我们现在显示的这个例子,如果它表示的是一个二进制数的相乘,我们就可以使用这个非常简洁的运算方法了,而这也正是计算机最终选择了二进制的一个重要的原因。其实最开始的电子计算机也是使用十进制的,我们不妨回到二十世纪四十年代去看两台我们非常熟悉的机器。
左边这一台就是ENIAC,它采用的就是十进制;而右边这一台是EDVAC,它采用的是二进制。那么ENIAC采用的是十进制,导致它内部设计的电路非常的复杂,而EDVAC采用的二进制之后就大大简化了控制逻辑。关于这一点,冯·诺依曼在他的报告中有详细的描述。
冯·诺依曼在关于EDVAC的报告草案中对于计算机应该采用什么样的进制,进行了详细的分析。他主要说了这么几点:
- 组成计算机的电子管是一种全或无的设备,它适合表示只有两个数值的系统,那么二进制就是一个合适的选择,这也是我们通常说计算机为什么要采用二进制的原因。但是仅仅有这一点是不够的;
- 还有一个重要的原因,就是要有适合的运算方法。在这份报告中冯·诺依曼还提到,二进制可以大幅地简化乘法和除法的运算过程。尤其是对于乘法,如果采用二进制,就不再需要使用十进制的乘法表,也不再需要产生每一个中间结果时所使用的加法了。
- 另外冯诺依曼还强调了一点,那就是十进制才是真正适合人类来使用的。无论计算机当中采用什么样的进制,最终和人进行交互时都应该使用十进制。因此,输入输出设备需要承担二进制和十进制之间的转换工作。
由此看来,如果想让计算机使用二进制而不是十进制,就必须要保证二进制在这个数值的表示和运算方面都需要有很好的性能的提升,要远远的超过格外的进制转换带来的性能损失这样才是可以接受的。
那好,我们再回来看这个二进制乘法的运算过程。现在我们有了非常简洁的运算方法,但是这个运算方法是否适合硬件的电路来实现呢?我们还需要来进一步的分析。
计算机的硬件资源和我们在纸上运算时可以比较随意地书写是不一样的,那么还是用在纸上进行计算作为例子,与刚才不同的是我们现在没有这么大一张纸了,我们把其中一部分(白色)剪掉,只留下了能写被乘数、乘数和乘积的这三行的位置。不过还有另一个变化就是我们不但有笔,而且还有橡皮,我们之前在纸上写的数可以用橡皮擦掉。那么就来看看在这么小的纸面上我们是否还能够完成刚才的乘法运算。
因为我们已经没有地方可以去记录中间的结果了,而在运算的最开始用来记录乘积的这个地方是空的,所以我们要想一想如何充分的利用这个区域。
在运算开始的时候我们可以把乘积记为0,然后我们开始运算。
第一步,对应的乘数位是1,所以我们现在已经知道这个中间结果就直接是被乘数。但是我们现在已经没有地方可以记录这个中间结果了,所以每产生一个中间结果我们就直接把它加到乘积上。
于是我们就用橡皮把现在的乘积的数给擦掉,然后写上新的乘积,其实也就是一个临时的中间结果,我们这样就完成了第一步。
在产生完这个中间结果之后,我们注意下一个中间结果实际上是往左错一位的。为了不至于过一会儿忘记了中间结果与乘积之间的对齐关系,我们现在就重新写一遍被乘数,把它放在下一个中间结果应该出现的对齐的位置。好了,然后我们再开始执行第二步的运算,这步中间结果是0,我们可以认为把这个0加到了现在的临时结果0001000上,也可以认为不做任何操作。
然后,我们会再把被乘数向左移动一位,再检查最后的乘数位还是0。
然后我们再把被乘数向左移动一位,再检查乘数的对应位是1,所以这一次的中间结果就是被乘数1000。
我们按照现在的被乘数和乘积之间的对齐关系,把这个中间结果加到当前的乘积上。我们注意, 现在我们已经检查完了乘数的每一位,所以这个运算已经完成了。
现在在这张纸的最下面这一行就是我们得到的最终的运算结果。这样我们就可以在没有空间记录中间结果的情况下完成了这个乘法的运算,这就是一个适合硬件的乘法运算的过程。
最后
以上就是害怕灰狼为你收集整理的乘法的运算过程的全部内容,希望文章能够帮你解决乘法的运算过程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复