一种二进制乘法的计算方法
计算机中数据都以二进制的形式存储,在对数据进行加、减、乘、除运算时计算机需要对二进制数据进行处理,而非人类熟悉的十进制。本文的目的是帮助大家理解计算机数据运算处理的过程,所以以较为简单的uint(无符号整数)类型数据为例来介绍它的乘法运算实现过程。本文提供的只是工野思考得出的一种方法,有其他方法和思路欢迎大家讨论。
一、数据左移n位等于数据乘以基数的n次幂
在十进制中,一位数字可以表示0-9十种状态,我们将一个数字左移一位,然后在个位补0,会看到结果和这个数字乘以10效果相同。假如我们选取一个数字6,将6左移一位,个位补0,结果如下:
可以证明数据左移一位,末位补0,等效于该数据乘以1位数据所能表示的数据个数。我们将1位数据所能表示的信息量(数据个数)定义为基数,那么可以有这样的描述:数据左移n位空位补0,等效于该数据乘以基数的n次幂。
(题外话:能不能给出这样的总结:所谓进制就是1位数据所能表示的信息量呢?比如二进制1位数据可以表示2种状态,八进制1位数据可以表示8种状态,十进制1位数据可以表示10种状态,十六进制1位数据可以表示16种状态……)
同理,二进制数据也具备同样的性质,二进制每位数据只能表示0或1两种状态,所以二进制数据左移1位,末位补0,等效于该二进制数乘以2。以此类推,左移2位、3位、4位等效于乘以4、8、16……
- 6*2=12
- 6*4=24
- 6*8=48
二、uint乘法实现
uint型数据是计算机(包括计算机、单片机、PLC等)中定义的一种无符号整数数据类型,在不同的系统中占用的位数不同,这里我们规定,本文的uint型数据占用8位数据。
在上文的推论中我们可知,当数据的乘数正好等于基数的x次幂时(x为正整数),相当于被乘数左移x位,在空位补0。
那如果乘数不等于基数的x次幂时,又是什么情况呢?比如二进制数6乘以二进制数5,常规计算过程如下:
根据数学运算法则,我们可将二进制6*5写成6*(4+1)=6*4+6*1,如下图:
这样我们将常规计算过程转换为了简单的移位问题,在二进制中1等于2的0次方,4等于2的2次方,所以计算如下:
可以证明,在二进制中任何数都可以转换为2的某次幂+2的某次幂+……之和,比如15的二进制表示为1111=1000+0100+0010+0001=2^3+2^2+2^1+2^0=8+4+2+1=15。
所以在程序中,只需将乘数二进制为1的位,按照上述方法对被乘数移位,最后将所有移位结果相加即可得到无符号整数相乘的结果。
三、计算溢出的判断
由于uint型数据的位数限制,当两数相乘的结果大于uint能表示的最大值时,将产生溢出,得到错误的结果。这是我们程序中不希望出现的情况,或者出现后必须进行处理的情况。那如何判断溢出的发生呢?
按照上文的计算方法,我们将无符号整数的乘法转换为了移位和加法问题。移位时被移出的位将被丢掉,因此,如果被移出的位中有为1的位,我们则可认为发生了数据溢出。在进行加法运算时,当最高位相加需要进位时,我们也可以认为发生了数据溢出,因为最高位的进位也将被丢掉。
以施耐德PLC为例(工野的看家饭碗),在进行移位运算时,以系统位%S17存储本次移出的最高位,如果在执行移位过程中任何一次此位为1,我们则可认为发生了数据溢出。在进行加法运算时,以系统位%S18存储加法运算的溢出状态,当此位为1,则发生了数据溢出。
在其它系统中也存在类似的系统状态位,大家在编程时可参考此方法判断数据溢出。
更多工控经验分享,欢迎关注"工控领域野钓人"。