不使用+运算符添加两个数字的最佳方法是什么?

时间:2008-12-13 18:13:51

标签: low-level addition

我和一个朋友来回与脑筋急转弯,我不知道如何解决这个问题。我的假设是,某些按位运算符是可能的,但不确定。

22 个答案:

答案 0 :(得分:39)

在C中,使用按位运算符:

#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)是无附加的加法。 (x & y)是每一位的结转。 (x & y) << 1是每个位的结转。

循环不断添加进位,直到所有位的进位为零。

答案 1 :(得分:22)

int add(int a, int b) {
   const char *c=0;
   return &(&c[a])[b];
}

答案 2 :(得分:10)

不是+对吗?

int add(int a, int b) 
{
   return -(-a) - (-b);
}

答案 3 :(得分:6)

定义“最佳”。这是一个python版本:

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

+执行列表连接,而不是添加。

答案 4 :(得分:5)

CMS的add()函数很漂亮。它不应该被一元否定所玷污(非按位运算,等于使用加法:-y ==(~y)+1)。所以这是一个使用相同的仅按位设计的减法函数:

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;
}

答案 5 :(得分:4)

注意,这适用于称为ripple-carry adder的加法器,它可以正常工作,但效果不佳。内置于硬件中的大多数二进制加法器是快速加法器的一种形式,例如carry-look-ahead adder

如果将carry_in设置为0,我的纹波进位加法器对无符号和2的补码整数都有效,如果将carry_in设置为1,则对1的补码整数有效。我还添加了标志来显示加法上的下溢或溢出。

#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;
}

答案 6 :(得分:4)

使用按位运算符的Java解决方案:

// 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;
}

答案 7 :(得分:4)

作弊。你可以否定数字并从第一个中减去它:)

如果失败,请查看二进制加法器的工作原理。 :)

编辑:啊,发布后看到了你的评论。

二进制加法的详细信息为here

答案 8 :(得分:2)

为什么不经常将第一个数字递增为第二个数字?

答案 9 :(得分:2)

ADD作为单个指令在汇编程序中实现的原因,而不是某种按位运算的组合,是很难做到的。您必须担心从给定的低阶位到下一个更高阶位的进位。这是机器在硬件中快速执行的操作,但即使使用C,也无法快速完成软件。

答案 10 :(得分:1)

基于Go的解决方案

func add(a int, b int) int {

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

return a 

}

可以按以下方法在Python中实现相同的解决方案,但是在Python中表示数字存在一些问题,Python的整数有32位以上。因此我们将使用掩码来获取最后的32位。

例如:如果不使用遮罩,则不会获得数字(-1,1)的结果

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

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

    return (a & mask) if b > mask else a

答案 11 :(得分:1)

在python中使用按位运算符:

def sum_no_arithmetic_operators(x,y):
    while True:
        carry = x & y
        x = x ^ y
        y = carry << 1
        if y == 0:
            break
    return x

答案 12 :(得分:1)

添加两个整数并不困难;网上有很多二进制加法的例子。

更具挑战性的问题是浮点数!在http://pages.cs.wisc.edu/~smoler/x86text/lect.notes/arith.flpt.html

上有一个例子

答案 13 :(得分:0)

我在编码面试中看到这是问题18.1。 我的python解决方案:

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)

此方法使用迭代,因此时间复杂度不是最佳的。 我认为最好的方法是通过按位操作在较低级别工作。

答案 14 :(得分:0)

这是一个可移植的单行三元和递归解决方案。

int add(int x, int y) {
    return y == 0 ? x : add(x ^ y, (x & y) << 1);
}

答案 15 :(得分:0)

这是C ++中的解决方案,您可以在我的github上找到它: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);
  }

答案 16 :(得分:0)

以与在纸上进行二元加法相同的方式实现。

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);
}

速度提升将低于::

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);
}

答案 17 :(得分:0)

我自己在C#中处理这个问题并且无法通过所有测试用例。然后我跑过this

这是C#6中的一个实现:

public int Sum(int a, int b) => b != 0 ? Sum(a ^ b, (a & b) << 1) : a;

答案 18 :(得分:0)

如果输入符号相反,则投票最多的答案将无效。然而,以下将。我在一个地方作弊,但只是为了保持代码有点干净。任何改进建议欢迎

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

答案 19 :(得分:0)

这是我在Python上的实现。当我们知道字节数(或位数)时,它运行良好。

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

答案 20 :(得分:0)

您可以使用位移和AND运算来完成。

#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;
}

答案 21 :(得分:-2)

Python代码: (1)

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

使用lambda函数&#39; - &#39;操作

(2)

add= lambda a,b : len(list(map(lambda x:x,(i for i in range(-a,b)))))