一、基础知识
做这题需要用到计算机组成原理的基础知识:二进制的表示以及加法器。
简要提下知识点,最好再去研究下来龙去脉,加深理解。
(1)二进制加法
a | b | 非进位和s | 进位c |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
对于非进位和,满足异或运算。
s
=
a
⨁
b
s=a \bigoplus b
s=a⨁b
对于进位,满足与运算。
c
=
a
&
b
c=a \& b
c=a&b
(2)二进制补码
对于有符号整数来说,首位是符号位,符号位是0表示正数,符号位为1表示负数,其余31位表示数值部分。
但,不论正数还是负数,在计算机中都是用二进制补码来存储的。
对于正数,补码、反码和其原码相同。
对于负数 ,补码等于其原码的反码再加1。
例:3,数值部分为11,符号位为0。
原码:00000000 00000000 00000000 00000011
反码:00000000 00000000 00000000 00000011
补码:00000000 00000000 00000000 00000011
例:-2,数值部分为10,符号为1.
原码:100000000 00000000 00000000 00000010
反码:1111111111 111111111 111111111 111111101
补码:1111111111 111111111 111111111 111111110
二进制的补码使得减法运算也能通过加法来实现。
例:-2 + 3 = 1
二、代码实现
C代码参考自评论区,相当简洁(不好理解):
int add(int a, int b){
int carry = 0;
while(b)
{
carry = (unsigned)(a&b)<<1;
a ^= b;
b = carry;
}
return a;
}
解释:两数相加的二进制加法模拟,
(1)通过与运算得到进位的值。有符号整数进行移位操作时,符号位没有移动,移位不能改变符号位的值。而在补码运算中,符号位要参与运算,所以在移位前要强转,将其当做无符号数来处理。进位比当前位要高1位,所以整体左移1位。
(2)通过异或运算得到非进位和。
(3)进位的值要和进位所在位进行相加,这就又回到了前面的步骤(1)(2),直到进位值为0。
时间复杂度 O ( 1 ) O(1) O(1),空间复杂度 O ( 1 ) O(1) O(1)。