我正在处理来自GeeksForGeeks的以下练习题:
编写一个返回两个整数之和的函数Add()。该函数不应使用任何算术运算符(+,++, - , - ,..等)。
C#中给出的解决方案是:
public static int Add(int x, int y)
{
// Iterate till there is no carry
while (y != 0)
{
// carry now contains common set bits of x and y
int carry = x & y;
// Sum of bits of x and y where at least one of the bits is not set
x = x ^ y;
// Carry is shifted by one so that adding it to x gives the required sum
y = carry << 1;
}
return x;
}
看看这个解决方案,我了解 它是如何发生的;我可以跟随调试器并在它们到来之前预测值的变化。但在经过几次之后,我仍然不明白为什么它正在发生。如果要在面试中提出,我将不得不依靠记忆来解决它,而不是实际理解算法是如何工作的。
有人可以帮助解释为什么我们在某些点使用某些运算符以及这些总数应该代表什么?我知道代码中已有评论,但我显然遗漏了一些东西......
答案 0 :(得分:4)
在每次迭代中,您都有以下步骤:
carry <- x & y // mark every location where the addition has a carry
x <- x ^ y // sum without carries
y <- carry << 1 // shift the carry left one column
在下一次迭代中,x
保存除了之外的整个和,用于进位位,它们位于y中。这些载物正好向左一列撞击,就像你在纸上做了添加一样。继续这样做,直到不再需要担心进位。
非常简单地说,这就像你或我在纸上做的那样添加,除了,它不是从右到左工作,而是并行完成所有的位。
答案 1 :(得分:1)
十进制算术比二进制算术更复杂,但也许有助于比较它们。
通常用于添加的算法是逐个遍历数字,记住&#34;携带一个&#34;必要时。在上面的算法中,这并不是恰好发生的事情 - 相反,所有数字都被添加并允许换行,并且所有收集的行都被收集起来,以便在下一步中一次性应用。在十进制中看起来像这样:
123456
777777
------ +
890123
001111 << 1
011110
------ +
801233
010000 << 1
100000
------ +
901233
000000 done
在二进制算术中,不带进位的加法只是异或。
答案 2 :(得分:-1)
这里有一个关于内存中的Representsenetation的二进制数学的例子: https://www.wikihow.com/Add-Binary-Numbers
通常在使用C#进行编程时,您不必理会&#34;它如何在内存中表示&#34;事情的层次。 55%的时间不值得努力,40%比使用内置功能更糟糕。剩下的5%你应该问问自己为什么你没有使用Native C ++,Assembler或具有类似低级别容量的东西进行编程。