计算两数之和不论在计算机中还是生活中,都不算难(即使某些数据过大)。但是如何能更高效的计算时一个难题,或者说在计算机内部是如何解析两个数之间的加法的,这就成了一个可以探讨的问题。
当然我们很了解十进制的算法,那么来看一组简单数组:
56+89
首先个位:6和9相加大于等于10,即会产生进位,此时我们只去个位相加后得出结果的个位,即6+9=15,我们取5,使1进到十位;
然后十位:5+8+1大于等于10,又会产生进位,此时依旧取结果中的个位4,并将十位进到下一位百位;
最后百位:1+0=1小于10,不会产生进位。
得出最终结果:145
同样二进制,一样的道理。但还是存在差异。
例如一组数据:0111,0101
正确答案为12—>1100
首先,获得进位的位置:很简单,两数相与,并左移一位,得到进位的位置。
很好理解,此时的第一、三为产生进位,进到第二、四位上,所以下次相加时给二、四位多加一。
首先要知道,二进制中,只有两个数,即0和1,所以一旦产生进位,或退位,必然也只是0和1。即1+1=10,10-01=01;
然后回头再看不考虑进位的情况下两数相加的结果,即两数相异或,得出0000 0010,其他位则需要进位或者本就为0,不需进位。
然后一直持续的检查进位标志是否需要进位,当为进位标志为0时,表示此时没有一位需要进位,则输出最终结果。
看代码:
int Add(int left,int right)
{
int CF=(left&right)<<1;//保存进位信息
left^=right;//保存不考虑进位的加法结果
//上述的表达式已经计算出不考虑进位的结果,和需要进位的标志位
//以下循环里面的都是关于结果和进位之间的计算
//相当于之前十进制的例子,56+89,先计算不考虑进位情况的结果:35,此时CF保存的进位为110
//给个位,十位,百位分别加上0,1,1,得出最终结果145;
while(CF)//有进位的情况下一直检测
{
right=CF;
CF=(left&right)<<1;//继续检测是否还有进位的位
left^=right;
//将不考虑进位的结果与上次需进位的位相异或,得出的结果依旧没有考虑是否进位存在
//且若此时的进位标志为0,不需要进位,则考虑不考虑是否进位都无关,所以是最终结果
//但若是依旧存在进位标志,则继续进行上述步骤。
}
return left;
}