34

A friend and I are going back and forth with brain-teasers and I have no idea how to solve this one. My assumption is that it's possible with some bitwise operators, but not sure.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
user23126
  • 2,051
  • 5
  • 18
  • 16

26 Answers26

57

In C, with bitwise operators:

#include<stdio.h>

int add(int x, int y) {
    int a, b;
    do {
        a = x & y;
        b = x ^ y;
        x = a << 1;
        y = b;
    } while (a);
    return b;
}


int main( void ){
    printf( "2 + 3 = %d", add(2,3));
    return 0;
}

XOR (x ^ y) is addition without carry. (x & y) is the carry-out from each bit. (x & y) << 1 is the carry-in to each bit.

The loop keeps adding the carries until the carry is zero for all bits.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • Thank you. I am afraid to ask, but does subtraction work similarly? I read that I can just add the two's complement. But when I try to, say, subtract 6-3, and turn that into 6+(-3) using two's complement, I get an infinite loop in the above algorithm. – user23126 Dec 13 '08 at 18:39
  • 1
    add(6, -3) should work, you can play with the code here: http://codepad.org/iWSRSsUn – Christian C. Salvadó Dec 13 '08 at 18:43
  • 8
    Left shifting a negative value is undefined behavior, it will work as expected on many processors but it isn't guaranteed, you should point this out in your answer. Also, can you add a \n to your printf statement? Aside from that, nice answer. – Robert Gamble Dec 13 '08 at 19:23
  • I tried converting your algorithm into Python (http://codepad.org/pb8IuLnY) and am experiencing an infinite loop when a negative number is passed in (i.e. the subtract). Are Python's operators any different than C? – user23126 Dec 13 '08 at 20:13
  • 1
    @pomeranian.myopenid.com, it is most likely due to the way the left-shift operator is handled in Python. Instead of reaching an upper limit on the integer bits, and setting the highest bit to make a number negative, it becomes positive long integers. – Lara Dougan Dec 14 '08 at 18:24
  • 1
    In theory, from a computer science perspective, addition isn't necessarily any different that subtraction. What it boils down to is how negative numbers are represented, simply because that 10-5 is no different than 10+(-5). Most likely you'd need to look in to twos complement, which is ones complement + 1, which again is the same as inverting all bit and adding 1. Keep in mind that this method will often cause overflow, though that shouldn't be a problem. I should mention that negative numbers can be represented differently, in which case the approach would need to be different. – Zacariaz Mar 31 '13 at 23:36
  • @ChristianC.Salvadó I know you answered long ago. But, I have a question. Is there any way we could do an addition operation with a bitwise operator but not using any loops? – F.C. Akhi Mar 24 '22 at 10:22
26
int add(int a, int b) {
   const char *c=0;
   return &(&c[a])[b];
}
epoch
  • 16,396
  • 4
  • 43
  • 71
ackb
  • 572
  • 3
  • 6
  • 3
    I didn't quite understand how this one works, an explanation would be great! – ffledgling Oct 24 '13 at 23:21
  • 7
    @ffledgling The address of `c` is initially 0. The address of `c[a]` is `0 + a = a`. And the address of `(&c[a])[b]` is `a + b`. Nice cheat, though still `add` is implicitly used. – Landys Sep 03 '14 at 03:24
  • 2
    Note that you need to allocate an array large enough for the largest sum. Otherwise, creating a pointer that exceeds an array bounds is *undefined behavior*. – Nayuki Jul 03 '16 at 05:17
  • @Nayuki This isn't an array, though. – wizzwizz4 Mar 16 '19 at 17:40
12

No + right?

int add(int a, int b) 
{
   return -(-a) - (-b);
}
davidfowl
  • 37,120
  • 7
  • 93
  • 103
  • 8
    In the question comments, @pomeranian.myopenid.com mentions that no arithmetic operators can be used. Besides, it would be better put as a - (-b) to use subtraction as the substitute operation. – Lara Dougan Dec 13 '08 at 19:17
5

CMS's add() function is beautiful. It should not be sullied by unary negation (a non-bitwise operation, tantamount to using addition: -y==(~y)+1). So here's a subtraction function using the same bitwise-only design:

int sub(int x, int y) {
    unsigned a, b;
    do {
        a = ~x & y;
        b =  x ^ y;
        x = b;
        y = a << 1;
    } while (a);
    return b;
}
Deadcode
  • 860
  • 9
  • 15
  • This does not provide an answer to the question, which is asking for addition, not subtraction. – MD XF Oct 03 '17 at 01:04
  • @MD XF, I was providing an answer to a question user23126 [asked in the comments of CMS's answer](https://stackoverflow.com/questions/365522/what-is-the-best-way-to-add-two-numbers-without-using-the-operator/2310745#comment195285_365544). I felt CMS's answer to this comment was unsatisfactory, since as I explained above, unary negation is tantamount to using addition. There is no way to put multi-line code in a comment, so I posted it as an answer. Also note that user23126 was the original question asker – so in a way, this does qualify as answering the question. – Deadcode Dec 08 '18 at 04:24
  • Also, while the question does literally ask how to add two numbers without using the + operator, it's trivially possible with `a - (-b)` as others stated. So answering how to do it without using any arithmetic operators is more in the spirit of the question. Also, user23126 [directly stated](https://stackoverflow.com/questions/365522/what-is-the-best-way-to-add-two-numbers-without-using-the-operator/2310745#comment196109_365573) that an operator which isn't literally `+` still isn't acceptable to use if it does addition, and `++` is very similar to part of what negation does behind the scenes. – Deadcode Dec 08 '18 at 04:43
5

Define "best". Here's a python version:

len(range(x)+range(y))

The + performs list concatenation, not addition.

amey91
  • 542
  • 6
  • 17
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
4

Cheat. You could negate the number and subtract it from the first :)

Failing that, look up how a binary adder works. :)

EDIT: Ah, saw your comment after I posted.

Details of binary addition are here.

Andrew Rollings
  • 14,340
  • 7
  • 51
  • 50
4

Note, this would be for an adder known as a ripple-carry adder, which works, but does not perform optimally. Most binary adders built into hardware are a form of fast adder such as a carry-look-ahead adder.

My ripple-carry adder works for both unsigned and 2's complement integers if you set carry_in to 0, and 1's complement integers if carry_in is set to 1. I also added flags to show underflow or overflow on the addition.

#define BIT_LEN 32
#define ADD_OK 0
#define ADD_UNDERFLOW 1
#define ADD_OVERFLOW 2

int ripple_add(int a, int b, char carry_in, char* flags) {
    int result = 0;
    int current_bit_position = 0;
    char a_bit = 0, b_bit = 0, result_bit = 0;

    while ((a || b) && current_bit_position < BIT_LEN) {
        a_bit = a & 1;
        b_bit = b & 1;
        result_bit = (a_bit ^ b_bit ^ carry_in);
        result |= result_bit << current_bit_position++;
        carry_in = (a_bit & b_bit) | (a_bit & carry_in) | (b_bit & carry_in);
        a >>= 1;
        b >>= 1;
    }

    if (current_bit_position < BIT_LEN) {
        *flags = ADD_OK;
    }
    else if (a_bit & b_bit & ~result_bit) {
        *flags = ADD_UNDERFLOW;
    }
    else if (~a_bit & ~b_bit & result_bit) {
        *flags = ADD_OVERFLOW;
    }
    else {
        *flags = ADD_OK;
    }

    return result;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Lara Dougan
  • 791
  • 4
  • 13
  • Unfortunately the increment operator (current_bit_position++) requires addition. Nitpicky, I know. – user23126 Dec 14 '08 at 16:50
  • 2
    @pomeranian.myopenid.com yeah, that is true in this case. In hardware, there is separate logic gates for each bit, and doesn't use a loop. If this loop were to be unrolled, you could use it without the ++ operator. – Lara Dougan Dec 14 '08 at 18:17
  • @Lara: Yes, unroll. For 32 bits it would be 32 copies of the code within the while-loop. This would give a nice hardware pseudocode and a bonus point: it is even executable! Programming hardware follows different rules than programming software, so some best practices don't apply here... – nalply Sep 20 '11 at 11:39
4

Java solution with bitwise operators:

// Recursive solution
public static int addR(int x, int y) {

    if (y == 0) return x;
    int sum = x ^ y; //SUM of two integer is X XOR Y
    int carry = (x & y) << 1;  //CARRY of two integer is X AND Y
    return addR(sum, carry);
}

//Iterative solution
public static int addI(int x, int y) {

    while (y != 0) {
        int carry = (x & y); //CARRY is AND of two bits
        x = x ^ y; //SUM of two bits is X XOR Y
        y = carry << 1; //shifts carry to 1 bit to calculate sum
    }
    return x;
}
realPK
  • 2,630
  • 29
  • 22
  • 1
    Removing the `public static` from both makes it work in C too. +1 – MD XF Oct 03 '17 at 01:08
  • 1
    This is exactly [CMS's answer](https://stackoverflow.com/questions/365522/what-is-the-best-way-to-add-two-numbers-without-using-the-operator/365544#365544) (the currently accepted one), but with meaningful variable names, and an explanation with inline comments instead of in the text (which CMS's answer was missing for years, but I added it in July 2016.) Still, upvoted for explaining it clearly and correctly. – Peter Cordes Oct 03 '17 at 01:24
  • Actually, it would be better to say that `xor` is add-without-carry. The first comment in the recursive version says it's the sum of two *integers*, which is wrong. – Peter Cordes Oct 03 '17 at 01:27
  • @PeterCordes CMS's answer includes a main method and is valid C code. What I have added here is valid Java methods only. This code is tested on my local machine and not directly copy pasted from other source. Thanks for your comments though. – realPK Oct 03 '17 at 07:03
4

Go based solution

func add(a int, b int) int {

for {
    carry := (a & b) << 1
    a = a ^ b
    b = carry 
    if b == 0 {
        break
    }
}

return a 

}

same solution can be implemented in Python as follows, but there is some problem about number represent in Python, Python has more than 32 bits for integers. so we will use a mask to obtain the last 32 bits.

Eg: if we don't use mask we won't get the result for numbers (-1,1)

def add(a,b):   
    mask = 0xffffffff

    while b & mask:
        carry = a & b
        a = a ^ b
        b = carry << 1

    return (a & mask)
Prajilesh
  • 661
  • 4
  • 11
  • It'd be simpler to just `return a&mask`. Checking to see if you might not need to just complicates the code, and `&` is cheap. – Peter Cordes Oct 13 '19 at 16:52
2

Why not just incremet the first number as often, as the second number?

Oliver Friedrich
  • 9,018
  • 9
  • 42
  • 48
2

The reason ADD is implememted in assembler as a single instruction, rather than as some combination of bitwise operations, is that it is hard to do. You have to worry about the carries from a given low order bit to the next higher order bit. This is stuff that the machines do in hardware fast, but that even with C, you can't do in software fast.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • If you manage to write something in C that exactly matches what a hardware `add` instruction does for all inputs that don't cause undefined behaviour, the compiler can use an `add`. We're in exactly that situation now for things like `popcnt`, where the only pure ISO C way to get a `popcnt` instruction is for the compiler to recognize an idiom and optimize your loop or bithack sequence into a `popcnt` (and yes compilers will do that). Or for a rotate. https://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c. – Peter Cordes Oct 03 '17 at 01:30
  • Obviously having a `+` operator in C is vastly better than the alternative, but ugly source would be the main problem, not slow code. Heh, or `foo = (int) &((char*)x)[y]` to use array-index syntax as a `+` operator, but even creating a bogus pointer is UB in C. – Peter Cordes Oct 03 '17 at 01:32
2

Here's a portable one-line ternary and recursive solution.

int add(int x, int y) {
    return y == 0 ? x : add(x ^ y, (x & y) << 1);
}
Edward J Beckett
  • 5,061
  • 1
  • 41
  • 41
1

I saw this as problem 18.1 in the coding interview. My python solution:

def foo(a, b):
"""iterate through a and b, count iteration via a list, check len"""
    x = []
    for i in range(a):
            x.append(a)
    for i in range(b):
            x.append(b)
    print len(x)

This method uses iteration, so the time complexity isn't optimal. I believe the best way is to work at a lower level with bitwise operations.

phuclv
  • 37,963
  • 15
  • 156
  • 475
James
  • 11
  • 2
1

In python using bitwise operators:

def sum_no_arithmetic_operators(x,y):
    while True:
        carry = x & y
        x = x ^ y
        y = carry << 1
        if y == 0:
            break
    return x
guribe94
  • 1,551
  • 3
  • 15
  • 29
  • this will error out for pairs (-1,1) , we have to use a mask to get the last 32 bits https://stackoverflow.com/questions/365522/what-is-the-best-way-to-add-two-numbers-without-using-the-operator/58365510#58365510 – Prajilesh Oct 13 '19 at 16:39
0

You can do it using bit-shifting and the AND operation.

#include <stdio.h>

int main()
{
    unsigned int x = 3, y = 1, sum, carry;
    sum = x ^ y; // Ex - OR x and y
    carry = x & y; // AND x and y
    while (carry != 0) {
        carry = carry << 1; // left shift the carry
        x = sum; // initialize x as sum
        y = carry; // initialize y as carry
        sum = x ^ y; // sum is calculated
        carry = x & y; /* carry is calculated, the loop condition is
                        evaluated and the process is repeated until
                        carry is equal to 0.
                        */
    }
    printf("%d\n", sum); // the program will print 4
    return 0;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
kyle k
  • 5,134
  • 10
  • 31
  • 45
0

Implemented in same way as we might do binary addition on paper.

int add(int x, int y)
{
    int t1_set, t2_set;
    int carry = 0;
    int result = 0;
    int mask = 0x1;

    while (mask != 0) {
        t1_set = x & mask;
        t2_set = y & mask;
        if (carry) {
           if (!t1_set && !t2_set) {
               carry = 0;
               result |= mask;
           } else if (t1_set && t2_set) {
               result |= mask;
           }
        } else {
           if ((t1_set && !t2_set) || (!t1_set && t2_set)) {
                result |= mask;
           } else if (t1_set && t2_set) {
                carry = 1;
           }
        }
        mask <<= 1;
    }
    return (result);
}

Improved for speed would be below::

int add_better (int x, int y)
{
  int b1_set, b2_set;
  int mask = 0x1;
  int result = 0;
  int carry = 0;

  while (mask != 0) {
      b1_set = x & mask ? 1 : 0;
      b2_set = y & mask ? 1 : 0;
      if ( (b1_set ^ b2_set) ^ carry)
          result |= mask;
      carry = (b1_set &  b2_set) | (b1_set & carry) | (b2_set & carry);
      mask <<= 1;
  }
  return (result);
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
0

Adding two integers is not that difficult; there are many examples of binary addition online.

A more challenging problem is floating point numbers! There's an example at http://pages.cs.wisc.edu/~smoler/x86text/lect.notes/arith.flpt.html

Paul
  • 6,435
  • 4
  • 34
  • 45
0

Was working on this problem myself in C# and couldn't get all test cases to pass. I then ran across this.

Here is an implementation in C# 6:

public int Sum(int a, int b) => b != 0 ? Sum(a ^ b, (a & b) << 1) : a;
Jake Smith
  • 2,332
  • 1
  • 30
  • 68
  • This is the same algorithm as the accepted answer, by CMS. – Peter Cordes Jul 06 '16 at 14:54
  • That is what I thought too, but that answer didn't pass all the test cases I had. So I offered what ended up working for me in a different programming language. Sometimes people happen upon questions long after they were posted and are in slightly different situations than the original poster. I hoped to help someone in a situation similar to the one I was. Sorry if I offended you, and feel free to edit my answer as well if you feel the need. – Jake Smith Jul 06 '16 at 15:09
  • I didn't look closely; how is your algo different from CMS's? Your recursion-end check is slightly different. Oh, should CMS's function check `while(x)` instead of `while(a)`? Anyway, if there's a problem with the accepted answer, you should comment on that either as a comment or as part of the text of this answer (or both). Anyway, I'm not personally offended, I just didn't think this answer was adding much value since what looks like the same algo was already posted. – Peter Cordes Jul 06 '16 at 15:17
  • There isn't a problem with it. It just doesn't translate to C# without augmentation. I think the key is a difference in language. I don't think negatives being shifted behave the same. In fact shifted negatives shouldn't guarantee that negatives be treated correctly in a mathematical sense because that's not the essence of a bit shift. My answer is specifically geared towards C# implementers and burying a comment that includes a solution that is different might get missed by someone that could be helped by this answer. – Jake Smith Jul 06 '16 at 15:50
0

It is my implementation on Python. It works well, when we know the number of bytes(or bits).

def summ(a, b):
    #for 4 bytes(or 4*8 bits)
    max_num = 0xFFFFFFFF
    while a != 0:
        a, b = ((a & b) << 1),  (a ^ b)
        if a > max_num:
            b = (b&max_num) 
            break
    return b
phuclv
  • 37,963
  • 15
  • 156
  • 475
Konstantin Purtov
  • 799
  • 1
  • 11
  • 19
0

The most voted answer will not work if the inputs are of opposite sign. The following however will. I have cheated at one place, but only to keep the code a bit clean. Any suggestions for improvement welcome

def add(x, y):
if (x >= 0 and y >= 0) or (x < 0 and y < 0):
    return _add(x, y)
else:
    return __add(x, y)


def _add(x, y):
if y == 0:
    return x
else:
    return _add((x ^ y), ((x & y) << 1))


def __add(x, y):
if x < 0 < y:
    x = _add(~x, 1)
    if x > y:
        diff = -sub(x, y)
    else:
        diff = sub(y, x)
    return diff
elif y < 0 < x:
    y = _add(~y, 1)
    if y > x:
        diff = -sub(y, x)
    else:
        diff = sub(y, x)
    return diff
else:
    raise ValueError("Invalid Input")


def sub(x, y):
if y > x:
    raise ValueError('y must be less than x')
while y > 0:
    b = ~x & y
    x ^= y
    y = b << 1
return x
phuclv
  • 37,963
  • 15
  • 156
  • 475
lalatnayak
  • 160
  • 1
  • 6
  • 21
  • *The most voted answer will not work if the inputs are of opposite sign* - It does work in C where integer types are fixed-width. (At least assuming 2's complement.) I tried it with negative numbers: https://godbolt.org/z/Lhyh4Y. Perhaps you mean it wouldn't work *in Python*? – Peter Cordes May 28 '20 at 20:18
0

Here is the solution in C++, you can find it on my github here: https://github.com/CrispenGari/Add-Without-Integers-without-operators/blob/master/main.cpp

int add(int a, int b){
   while(b!=0){
      int sum = a^b; // add without carrying
      int carry = (a&b)<<1; // carrying without adding
      a= sum;
      b= carry;
    }
   return a;
 }
 // the function can be writen as follows :
 int add(int a, int b){
     if(b==0){
        return a; // any number plus 0 = that number simple!
    }
    int sum = a ^ b;// adding without carrying;
    int carry = (a & b)<<1; // carry, without adding
    return add(sum, carry);
  }
crispengari
  • 7,901
  • 7
  • 45
  • 53
0
This can be done using Half Adder.
Half Adder is method to find sum of numbers with single bit.
A   B    SUM   CARRY   A & B    A ^ B
0   0    0     0        0         0
0   1    1     0        0         1
1   0    1     0        0         1
1   1    0     1        0         0

We can observe here that SUM = A ^ B and CARRY = A & B
We know CARRY is always added at 1 left position from where it was 
generated.
so now add ( CARRY << 1 ) in SUM, and repeat this process until we get 
Carry 0.

int Addition( int a, int b)
{
 if(B==0)
    return A;
 Addition( A ^ B, (A & B) <<1 )
}

let's add 7 (0111) and 3 (0011) answer will be 10 (1010)
  1. A = 0100 and B = 0110
  2. A = 0010 and B = 1000
  3. A = 1010 and B = 0000 final answer is A.
Hareesh
  • 13
  • 2
0

I implemented this in Swift, I am sure someone will benefit from

   var a = 3
   var b = 5
   var sum = 0
   var carry = 0

   while (b != 0) {
      sum = a ^ b
      carry = a & b
      a = sum
      b = carry << 1
   }

   print (sum)
Criss Gibran
  • 104
  • 2
  • 5
0

You can do it iteratively or recursively.
Recursive:-

public int getSum(int a, int b) {
    return (b==0) ? a : getSum(a^b, (a&b)<<1);
}

Iterative:-

public int getSum(int a, int b) {
    int c=0;
    while(b!=0) {
        c=a&b;
        a=a^b;
        b=c<<1;
    }
    return a;
}

time complexity - O(log b)
space complexity - O(1)
for further clarifications if not clear, refer leetcode or geekForGeeks explanations.

Wimukthi Rajapaksha
  • 961
  • 1
  • 11
  • 23
0

I'll interpret this question as forbidding the +,-,* operators but not ++ or -- since the question specified operator and not character (and also because that's more interesting).

A reasonable solution using the increment operator is as follows:

int add(int a, int b) {
  if (b == 0)
    return a;

  if (b > 0)
    return add(++a, --b);
  else
    return add(--a, ++b);
}

This function recursively nudges b towards 0, while giving a the same amount to keep the sum the same.

As an additional challenge, let's get rid of the second if block to avoid a conditional jump. This time we'll need to use some bitwise operators:

int add(int a, int b) {

  if(!b)
    return a;

  int gt = (b > 0);
  int m = -1 << (gt << 4) << (gt << 4);

  return (++a & --b & 0)
         | add( (~m & a--) | (m & --a),
                (~m & b++) | (m & ++b)
              );
}

The function trace is identical; a and b are nudged between each add call just like before. However, some bitwise magic is employed to drop the if statement while continuing to not use +,-,*:

A mask m is set to 0xFFFFFFFF (-1 in signed decimal) if b is positive, or 0x00000000 if b is negative.

The reason for shifting the mask left by 16 twice instead a single shift left by 32 is because shifting by >= the size of the value is undefined behavior.

The final return takes a bit of thought to fully appreciate:

Consider this technique to avoid a branch when deciding between two values. Of the values, one is multiplied by the boolean while the other is multiplied by the inverse, and the results are summed like so:

double naiveFoodPrice(int ownPetBool) {
  if(ownPetBool)
    return 23.75;
  else
    return 10.50;
}

double conditionlessFoodPrice(int ownPetBool) {
  double result = ownPetBool*23.75 + (!ownPetBool)*10.50;
}

This technique works great in most cases. For us, the addition operator can easily be substituted for the bitwise or | operator without changing the behavior.

The multiplication operator is also not allowed for this problem. This is the reason for our earlier mask value - a bitwise and & with the mask will achieve the same effect as multiplying by the original boolean.

The nature of the unary increment and decrement operators halts our progress. Normally, we would easily be able to choose between an a which was incremented by 1 and an a which was decremented by 1. However, because the increment and decrement operators modify their operand, our conditionless code will end up always performing both operations - meaning that the values of a and b will be tainted before we finish using them.

One way around this is to simply create new variables which each contain the original values of a and b, allowing a clean slate for each operation. I consider this boring, so instead we will adjust a and b in a way that does not affect the rest of the code (++a & --b & 0) in order to make full use of the differences between x++ and ++x.

We can now get both possible values for a and b, as the unary operators modifying the operands' values now works in our favor. Our techniques from earlier help us choose the correct versions of each, and we now have a working add function. :)

-2

Python codes: (1)

add = lambda a,b : -(-a)-(-b)

use lambda function with '-' operator

(2)

add= lambda a,b : len(list(map(lambda x:x,(i for i in range(-a,b)))))
nk911
  • 477
  • 4
  • 3