owned this note
owned this note
Published
Linked with GitHub
###### tags: `leetcode`
# #371 Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example 1:
Input: a = 1, b = 2
Output: 3
Example 2:
Input: a = -2, b = 3
Output: 1
## python3 sum()
```python=
class Solution(object):
def getSum(self, a, b):
"""
:type a: int
:type b: int
:rtype: int
"""
return sum([a, b])
```
## Bitwise operation on C
try to use C to do bitwise
- `&`
- bitwise AND
- `|`
- bitwise inclusive OR
- `^`
- bitwise XOR (eXclusive OR)
- `<<`
- left shift
- `>>`
- right shift
- `~`
- bitwise NOT (one's complement) (unary)
### use the fact that `2's complement=1's complement+1`
#### reference
http://puremonkey2010.blogspot.com/2011/05/c-bitwise-operation.html
#### A simple test
```cpp=
#include<stdio.h>
int addone(int);
int minusone(int);
int main() {
for (int i = 0; i < 10; i = addone(i)) {
printf("%d", i);
}
for (int i = 9; i > -1; i = minusone(i)) {
printf("%d", i);
}
}
int addone(int x) {
return -~x; // x + 1
}
int minusone(int x) {
return ~-x; // x - 1
}
```
### try 0
```cpp=
int addone(int);
int minusone(int);
int getSum(int a, int b){
if (b >= 0) {
for (int i = 0; i < b; i = addone(i)) {
a = addone(a);
}
}
if (b < 0) {
for (int i = 0; i < -b; i = addone(i)) {
a = minusone(a);
}
}
return a;
}
int addone(int x) {
return -~x; // x + 1
}
int minusone(int x) {
return ~-x; // x - 1
}
```
:::danger
Line 12: Char 29: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself (solution.c)
:::
:::info
Last executed input
2147483647
-2147483648
:::
#### Overflow
-2147483648 is the under-bound of 32-bit int.
Nevigation if it leads to 2147483648, and this is over the upper-bound of 32-bit int (214748364).
##### Revision
In the for-loop, void using `-b`.
### try 1
#### Do experiment
```cpp=
#include <stdio.h>
#include <stdlib.h>
int getSum(int, int);
int addone(int);
int minusone(int);
int main(){
int a = 2147483647;
int b = -2147483648;
// int a = -5;
// int b = -2;
printf("%d", getSum(a,b));
}
int getSum(int a, int b){
printf("a = %d\n",a);
printf("b = %d\n",b);
if (b >= 0) {
for (int i = 0; i < b; i = addone(i)) {
a = addone(a);
//printf(" a = %d\n",a);
}
}
if (b < 0) {
//for (int i = 0; i < -b; i = addone(i)) {
for (int i = b; i < 0; i = addone(i)) {
a = minusone(a);
//printf(" a = %d\n",a);
}
}
return a;
}
int addone(int x) {
return -~x; // x + 1
}
int minusone(int x) {
return ~-x; // x - 1
}
```
:::warning
int a = 2147483647;
int b = -2147483648;
is too large for some online compiler
:::
#### LeetCode
```cpp=
int addone(int);
int minusone(int);
int getSum(int a, int b){
if (b >= 0) {
for (int i = 0; i < b; i = addone(i)) {
a = addone(a);
}
}
if (b < 0) {
for (int i = b; i < 0; i = addone(i)) {
a = minusone(a);
}
}
return a;
}
int addone(int x) {
return -~x; // x + 1
}
int minusone(int x) {
return ~-x; // x - 1
}
```
:::success
Runtime: 1200 ms, faster than 5.54% of C online submissions for Sum of Two Integers.
Memory Usage: 6.8 MB, less than 12.84% of C online submissions for Sum of Two Integers.
:::
### try 2
Try to improve runtime.
Use the idea here
https://leetcode.com/problems/sum-of-two-integers/discuss/84305/Share-my-C%2B%2B-solutionseasy-to-understand
The main idea is to add a and b to c, without considering carry.
Then add c and carry, recursively, until no carry.
```cpp=
int getSum(int a, int b){
int direct_sum_without_carry = a ^ b; // XOR
int carry = a & b; // AND
while (carry != 0){
a = direct_sum_without_carry;
b = carry;
direct_sum_without_carry = a ^ b; // XOR
carry = a & b; // AND
}
int direct_sum_with_all_carry = direct_sum_without_carry;
return direct_sum_with_all_carry;
}
```
:::danger
Wrong Answer
Input
2
3
Output
3
Expected
5
:::
:::warning
I didn't do the left-shift
:::
### try 3
```cpp=
int getSum(int a, int b){
int direct_sum_without_carry = a ^ b; // XOR
int carry = a & b; // AND
while (carry != 0){
a = direct_sum_without_carry;
b = carry << 1;
direct_sum_without_carry = a ^ b; // XOR
carry = a & b; // AND
}
int direct_sum_with_all_carry = direct_sum_without_carry;
return direct_sum_with_all_carry;
}
```
:::danger
Line 6: Char 19: runtime error: left shift of 1073741824 by 1 places cannot be represented in type 'int' (solution.c)
:::
:::danger
Last executed input
-1
1
:::
#### Reason of failure
1073741824 = 2^30
= 01000000000000000000000000000000
A left-shift of 1073741824 leads to 2^31 and thus overflow.
Recall that the upper bound of (signed) integer is 2^31-1.
#### Revision
I have to consider minus number and overflow.
##### experiment
Environment is on https://www.onlinegdb.com/online_c_compiler
```cpp=
#include <stdio.h>
void print2(int x) {
for (int c = 31; c >= 0; c--) {
int k = x >> c;
if (k & 1)
printf("1");
else
printf("0");
}
printf("\n");
}
int getSum(int a, int b){
int direct_sum_without_carry = a ^ b; // XOR
printf("before the while; XOR; direct_sum_without_carry %d\n", direct_sum_without_carry);
print2(direct_sum_without_carry);
int carry = a & b; // AND
printf("before the while; AND; carry %d\n", carry);
print2(carry);
while (carry != 0){
a = direct_sum_without_carry;
b = carry << 1;
direct_sum_without_carry = a ^ b; // XOR
printf(" direct_sum_without_carry %12d ", direct_sum_without_carry);
print2(direct_sum_without_carry);
carry = a & b; // AND
printf(" carry %12d ", carry);
print2(carry);
}
int direct_sum_with_all_carry = direct_sum_without_carry;
return direct_sum_with_all_carry;
}
int main() {
int a = -1;
int b = 1;
printf("%d\n", getSum(a,b));
return 0;
}
```
This will work. It overflows and go back to 1.
```typescript=
before the while; XOR; direct_sum_without_carry -2
11111111111111111111111111111110
before the while; AND; carry 1
00000000000000000000000000000001
direct_sum_without_carry -4 11111111111111111111111111111100
carry 2 00000000000000000000000000000010
direct_sum_without_carry -8 11111111111111111111111111111000
carry 4 00000000000000000000000000000100
direct_sum_without_carry -16 11111111111111111111111111110000
carry 8 00000000000000000000000000001000
direct_sum_without_carry -32 11111111111111111111111111100000
carry 16 00000000000000000000000000010000
direct_sum_without_carry -64 11111111111111111111111111000000
carry 32 00000000000000000000000000100000
direct_sum_without_carry -128 11111111111111111111111110000000
carry 64 00000000000000000000000001000000
direct_sum_without_carry -256 11111111111111111111111100000000
carry 128 00000000000000000000000010000000
direct_sum_without_carry -512 11111111111111111111111000000000
carry 256 00000000000000000000000100000000
direct_sum_without_carry -1024 11111111111111111111110000000000
carry 512 00000000000000000000001000000000
direct_sum_without_carry -2048 11111111111111111111100000000000
carry 1024 00000000000000000000010000000000
direct_sum_without_carry -4096 11111111111111111111000000000000
carry 2048 00000000000000000000100000000000
direct_sum_without_carry -8192 11111111111111111110000000000000
carry 4096 00000000000000000001000000000000
direct_sum_without_carry -16384 11111111111111111100000000000000
carry 8192 00000000000000000010000000000000
direct_sum_without_carry -32768 11111111111111111000000000000000
carry 16384 00000000000000000100000000000000
direct_sum_without_carry -65536 11111111111111110000000000000000
carry 32768 00000000000000001000000000000000
direct_sum_without_carry -131072 11111111111111100000000000000000
carry 65536 00000000000000010000000000000000
direct_sum_without_carry -262144 11111111111111000000000000000000
carry 131072 00000000000000100000000000000000
direct_sum_without_carry -524288 11111111111110000000000000000000
carry 262144 00000000000001000000000000000000
direct_sum_without_carry -1048576 11111111111100000000000000000000
carry 524288 00000000000010000000000000000000
direct_sum_without_carry -2097152 11111111111000000000000000000000
carry 1048576 00000000000100000000000000000000
direct_sum_without_carry -4194304 11111111110000000000000000000000
carry 2097152 00000000001000000000000000000000
direct_sum_without_carry -8388608 11111111100000000000000000000000
carry 4194304 00000000010000000000000000000000
direct_sum_without_carry -16777216 11111111000000000000000000000000
carry 8388608 00000000100000000000000000000000
direct_sum_without_carry -33554432 11111110000000000000000000000000
carry 16777216 00000001000000000000000000000000
direct_sum_without_carry -67108864 11111100000000000000000000000000
carry 33554432 00000010000000000000000000000000
direct_sum_without_carry -134217728 11111000000000000000000000000000
carry 67108864 00000100000000000000000000000000
direct_sum_without_carry -268435456 11110000000000000000000000000000
carry 134217728 00001000000000000000000000000000
direct_sum_without_carry -536870912 11100000000000000000000000000000
carry 268435456 00010000000000000000000000000000
direct_sum_without_carry -1073741824 11000000000000000000000000000000
carry 536870912 00100000000000000000000000000000
direct_sum_without_carry -2147483648 10000000000000000000000000000000
carry 1073741824 01000000000000000000000000000000
direct_sum_without_carry 0 00000000000000000000000000000000
carry -2147483648 10000000000000000000000000000000
direct_sum_without_carry 0 00000000000000000000000000000000
carry 0 00000000000000000000000000000000
0
```
##### Question
I want to know how to determine that there will be 32 bits.
By `sizeof(int)`, I get a `4`, which is 16 bits.
https://hackmd.io/kzk9OFoYSPGLEO6A0wq9KA
### try 4
Edit from
`b = carry << 1;`
to
`b = (carry & 0xffffffff) << 1;`
Then it works!
```cpp=
int getSum(int a, int b){
int direct_sum_without_carry = a ^ b; // XOR
int carry = a & b; // AND
while (carry != 0){
a = direct_sum_without_carry;
b = (carry & 0xffffffff) << 1;
direct_sum_without_carry = a ^ b; // XOR
carry = a & b; // AND
}
int direct_sum_with_all_carry = direct_sum_without_carry;
return direct_sum_with_all_carry;
}
```
:::success
Success
Runtime: 0 ms, faster than 100.00% of C online submissions for Sum of Two Integers.
Memory Usage: 6.7 MB, less than 19.59% of C online submissions for Sum of Two Integers.
:::
I don't why use `b = (carry & 0xffffffff) << 1;` can avoid the error from try 3 on Leetcode.
>Line 6: Char 19: runtime error: left shift of 1073741824 by 1 places cannot be represented in type ‘int’ (solution.c)
>
`0xffffffff` is merly 32 1's.
It seem like if I use `carry & 0xffffffff` then I can do operations with overflows.
### try 5
```cpp=
int getSum(int a, int b){
long long carry; // 64-bit
long long temp; // 64-bit
while (b != 0) {
carry = a & b;
a = a ^ b;
temp = ((carry) << 1);
b = (int) temp;
}
return a;
}
```
:::danger
Runtime Error
Line 7: Char 25: runtime error: left shift of negative value -2147483648 (solution.c)
Last executed input
-1
1
:::
-2147483648
= 10000000000000000000000000000000
### try 6
A more compact version of try 4.
```cpp=
int getSum(int a, int b){
int carry; // 64-bit
while (b != 0) {
carry = a & b;
a = a ^ b;
b = ((carry & 0xffffffff) << 1);
}
return a;
}
```
Still `& 0xffffffff` is required, or it will fail by
> Line 6: Char 23: runtime error: left shift of 1073741824 by 1 places cannot be represented in type 'int' (solution.c)
Last executed input
-1
1