简体   繁体   English

如何在不使用 ++ 或 + 或其他算术运算符的情况下将两个数字相加

[英]How to add two numbers without using ++ or + or another arithmetic operator

How do I add two numbers without using ++ or + or any other arithmetic operator?如何在不使用 ++ 或 + 或任何其他算术运算符的情况下将两个数字相加?

It was a question asked a long time ago in some campus interview.这是很久以前在一些校园面试中提出的问题。 Anyway, today someone asked a question regarding some bit-manipulations, and in answers a beautiful quide Stanford bit twiddling was referred.不管怎么说,今天有人问一些关于位操作一个问题,在回答一个美丽的quide斯坦福位操作被提到。 I spend some time studying it and thought that there actually might be an answer to the question.我花了一些时间研究它,并认为这个问题实际上可能有答案。 I don't know, I could not find one.我不知道,我找不到一个。 Does an answer exist?有答案吗?

This is something I have written a while ago for fun.这是我前一段时间写的东西,为了好玩。 It uses a two's complement representation and implements addition using repeated shifts with a carry bit, implementing other operators mostly in terms of addition.它使用二进制补码表示,并使用带有进位的重复移位来实现加法,主要以加法来实现其他运算符。

#include <stdlib.h> /* atoi() */
#include <stdio.h>  /* (f)printf */
#include <assert.h> /* assert() */

int add(int x, int y) {
    int carry = 0;
    int result = 0;
    int i;

    for(i = 0; i < 32; ++i) {
        int a = (x >> i) & 1;
        int b = (y >> i) & 1;
        result |= ((a ^ b) ^ carry) << i;
        carry = (a & b) | (b & carry) | (carry & a);
    }

    return result;
}

int negate(int x) {
    return add(~x, 1);
}

int subtract(int x, int y) {
    return add(x, negate(y));
}

int is_even(int n) {
    return !(n & 1);
}

int divide_by_two(int n) {
    return n >> 1;
}

int multiply_by_two(int n) {
    return n << 1;
}

int multiply(int x, int y) {
    int result = 0;

    if(x < 0 && y < 0) {
        return multiply(negate(x), negate(y));
    }

    if(x >= 0 && y < 0) {
        return multiply(y, x);
    }

    while(y > 0) {
        if(is_even(y)) {
            x = multiply_by_two(x);
            y = divide_by_two(y);
        } else {
            result = add(result, x);
            y = add(y, -1);
        }
    }

    return result;
}

int main(int argc, char **argv) {
    int from = -100, to = 100;
    int i, j;

    for(i = from; i <= to; ++i) {
        assert(0 - i == negate(i));
        assert(((i % 2) == 0) == is_even(i));
        assert(i * 2 == multiply_by_two(i));
        if(is_even(i)) {
            assert(i / 2 == divide_by_two(i));
        }
    }

    for(i = from; i <= to; ++i) {
        for(j = from; j <= to; ++j) {
            assert(i + j == add(i, j));
            assert(i - j == subtract(i, j));
            assert(i * j == multiply(i, j));
        }
    }

    return 0;
}

Or, rather than Jason's bitwise approach, you can calculate many bits in parallel - this should run much faster with large numbers.或者,您可以并行计算许多位,而不是 Jason 的按位方法 - 这应该在处理大量数字时运行得更快。 In each step figure out the carry part and the part that is sum.在每一步中找出进位部分和总和部分。 You attempt to add the carry to the sum, which could cause carry again - hence the loop.您尝试将进位添加到总和中,这可能会再次导致进位 - 因此循环。

>>> def add(a, b):
    while a != 0:
        #      v carry portion| v sum portion
        a, b = ((a & b) << 1),  (a ^ b)
        print b, a
    return b

when you add 1 and 3, both numbers have the 1 bit set, so the sum of that 1+1 carries.当您将 1 和 3 相加时,两个数字都设置了 1 位,因此 1+1 的总和进位。 The next step you add 2 to 2 and that carries into the correct sum four.下一步,您将 2 加到 2,然后得出正确的总和四。 That causes an exit这会导致退出

>>> add(1,3)
2 2
4 0
4

Or a more complex example或者更复杂的例子

>>> add(45, 291)
66 270
4 332
8 328
16 320
336

Edit: For it to work easily on signed numbers you need to introduce an upper limit on a and b编辑:为了在有符号数字上轻松工作,您需要在 a 和 b 上引入上限

>>> def add(a, b):
    while a != 0:
        #      v carry portion| v sum portion
        a, b = ((a & b) << 1),  (a ^ b)
        a &= 0xFFFFFFFF
        b &= 0xFFFFFFFF
        print b, a
    return b

Try it on试试

add(-1, 1)

to see a single bit carry up through the entire range and overflow over 32 iterations看到单个位在整个范围内向上进位并在 32 次迭代中溢出

4294967294 2
4294967292 4
4294967288 8
...
4294901760 65536
...
2147483648 2147483648
0 0
0L
int Add(int a, int b)
{
    while (b)
    {
        int carry = a & b;
        a = a ^ b;
        b = carry << 1;
    }
    return a;
}

You could transform an adder circuit into an algorithm.您可以将加法器电路转换为算法。 They only do bitwise operations =)他们只做按位运算 =)

Well, to implement an equivalent with boolean operators is quite simple: you do a bit-by-bit sum (which is an XOR), with carry (which is an AND).好吧,用布尔运算符实现等价物非常简单:你做一个逐位求和(这是一个异或),进位(这是一个与)。 Like this:像这样:

int sum(int value1, int value2)
{
    int result = 0;
    int carry = 0;
    for (int mask = 1; mask != 0; mask <<= 1)
    {
        int bit1 = value1 & mask;
        int bit2 = value2 & mask;
        result |= mask & (carry ^ bit1 ^ bit2);
        carry = ((bit1 & bit2) | (bit1 & carry) | (bit2 & carry)) << 1;
    }
    return result;
}

You've already gotten a couple bit manipulation answers.你已经得到了一些操作的答案。 Here's something different.这里有一些不同的东西。

In C, arr[ind] == *(arr + ind) .在 C 中, arr[ind] == *(arr + ind) This lets us do slightly confusing (but legal) things like int arr = { 3, 1, 4, 5 }; int val = 0[arr];这让我们可以做一些有点混乱(但合法)的事情,比如int arr = { 3, 1, 4, 5 }; int val = 0[arr]; int arr = { 3, 1, 4, 5 }; int val = 0[arr]; . .

So we can define a custom add function (without explicit use of an arithmetic operator) thusly:所以我们可以这样定义一个自定义的 add 函数(不显式使用算术运算符):

unsigned int add(unsigned int const a, unsigned int const b)
{
    /* this works b/c sizeof(char) == 1, by definition */
    char * const aPtr = (char *)a;
    return (int) &(aPtr[b]);
}

Alternately, if we want to avoid this trick, and if by arithmetic operator they include |或者,如果我们想避免这个技巧,并且如果通过算术运算符,它们包括| , & , and ^ (so direct bit manipulation is not allowed) , we can do it via lookup table: , &^ (因此不允许直接位操作),我们可以通过查找表来完成:

typedef unsigned char byte;

const byte lut_add_mod_256[256][256] = { 
  { 0, 1, 2, /*...*/, 255 },
  { 1, 2, /*...*/, 255, 0 },
  { 2, /*...*/, 255, 0, 1 },
  /*...*/
  { 254, 255, 0, 1, /*...*/, 253 },
  { 255, 0, 1, /*...*/, 253, 254 },
}; 

const byte lut_add_carry_256[256][256] = {
  { 0, 0, 0, /*...*/, 0 },
  { 0, 0, /*...*/, 0, 1 },
  { 0, /*...*/, 0, 1, 1 },
  /*...*/
  { 0, 0, 1, /*...*/, 1 },
  { 0, 1, 1, /*...*/, 1 },
};

void add_byte(byte const a, byte const b, byte * const sum, byte * const carry)
{
  *sum = lut_add_mod_256[a][b];
  *carry = lut_add_carry_256[a][b];
}

unsigned int add(unsigned int a, unsigned int b)
{
  unsigned int sum;
  unsigned int carry;
  byte * const aBytes = (byte *) &a;
  byte * const bBytes = (byte *) &b;
  byte * const sumBytes = (byte *) &sum;
  byte * const carryBytes = (byte *) &carry;

  byte const test[4] = { 0x12, 0x34, 0x56, 0x78 };
  byte BYTE_0, BYTE_1, BYTE_2, BYTE_3;

  /* figure out endian-ness */
  if (0x12345678 == *(unsigned int *)test)
  {
    BYTE_0 = 3;
    BYTE_1 = 2;
    BYTE_2 = 1;
    BYTE_3 = 0;
  }
  else 
  {
    BYTE_0 = 0;
    BYTE_1 = 1;
    BYTE_2 = 2;
    BYTE_3 = 3;
  }


  /* assume 4 bytes to the unsigned int */
  add_byte(aBytes[BYTE_0], bBytes[BYTE_0], &sumBytes[BYTE_0], &carryBytes[BYTE_0]);

  add_byte(aBytes[BYTE_1], bBytes[BYTE_1], &sumBytes[BYTE_1], &carryBytes[BYTE_1]);
  if (carryBytes[BYTE_0] == 1)
  {
    if (sumBytes[BYTE_1] == 255)
    {
      sumBytes[BYTE_1] = 0;
      carryBytes[BYTE_1] = 1;
    }
    else
    {
      add_byte(sumBytes[BYTE_1], 1, &sumBytes[BYTE_1], &carryBytes[BYTE_0]);
    }
  }

  add_byte(aBytes[BYTE_2], bBytes[BYTE_2], &sumBytes[BYTE_2], &carryBytes[BYTE_2]);
  if (carryBytes[BYTE_1] == 1)
  {
    if (sumBytes[BYTE_2] == 255)
    {
      sumBytes[BYTE_2] = 0;
      carryBytes[BYTE_2] = 1;
    }
    else
    {
      add_byte(sumBytes[BYTE_2], 1, &sumBytes[BYTE_2], &carryBytes[BYTE_1]);
    }
  }

  add_byte(aBytes[BYTE_3], bBytes[BYTE_3], &sumBytes[BYTE_3], &carryBytes[BYTE_3]);
  if (carryBytes[BYTE_2] == 1)
  {
    if (sumBytes[BYTE_3] == 255)
    {
      sumBytes[BYTE_3] = 0;
      carryBytes[BYTE_3] = 1;
    }
    else
    {
      add_byte(sumBytes[BYTE_3], 1, &sumBytes[BYTE_3], &carryBytes[BYTE_2]);
    }
  }

  return sum;
}

All arithmetic operations decompose to bitwise operations to be implemented in electronics, using NAND, AND, OR, etc. gates.所有算术运算都分解为要在电子设备中实现的按位运算,使用 NAND、AND、OR 等门。

Adder composition can be seen here .加法器组成可以在这里看到

For unsigned numbers, use the same addition algorithm as you learned in first class, but for base 2 instead of base 10. Example for 3+2 (base 10), ie 11+10 in base 2:对于无符号数,使用与您在第一堂课中学到的相同的加法算法,但用于基数 2 而不是基数 10。 3+2(基数 10)的示例,即基数 2 中的 11+10:

   1         ‹--- carry bit
   0 1 1     ‹--- first operand (3)
 + 0 1 0     ‹--- second operand (2)
 -------
   1 0 1     ‹--- total sum (calculated in three steps)

If you're feeling comedic, there's always this spectacularly awful approach for adding two (relatively small) unsigned integers.如果您觉得很喜剧,那么添加两个(相对较小的)无符号整数总是有这种非常糟糕的方法。 No arithmetic operators anywhere in your code.代码中的任何地方都没有算术运算符。

In C#:在 C# 中:

static uint JokeAdder(uint a, uint b)
{
    string result = string.Format(string.Format("{{0,{0}}}{{1,{1}}}", a, b), null, null);
    return result.Length;
}

In C, using stdio (replace snprintf with _snprintf on Microsoft compilers):在 C 中,使用 stdio(在 Microsoft 编译器上用 _snprintf 替换 snprintf):

#include <stdio.h>
unsigned int JokeAdder(unsigned int a, unsigned int b)
{
    return snprintf(NULL, 0, "%*.*s%*.*s", a, a, "", b, b, "");
}

Here is a compact C solution.这是一个紧凑的 C 解决方案。 Sometimes recursion is more readable than loops.有时递归比循环更具可读性。

int add(int a, int b){
    if (b == 0) return a;
    return add(a ^ b, (a & b) << 1);
}
short int ripple_adder(short int a, short int b)
{
    short int i, c, s, ai, bi;

    c = s = 0;

    for (i=0; i<16; i++)
    {
        ai = a & 1;
        bi = b & 1;

        s |= (((ai ^ bi)^c) << i);
        c = (ai & bi) | (c & (ai ^ bi));

        a >>= 1;
        b >>= 1;
    }
    s |= (c << i);
    return s;
}
#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;
}
## to add or subtract without using '+' and '-' ## 
#include<stdio.h>
#include<conio.h>
#include<process.h>

void main()
{
    int sub,a,b,carry,temp,c,d;

    clrscr();

    printf("enter a and b:");
    scanf("%d%d",&a,&b);

    c=a;
    d=b;
    while(b)
    {
        carry=a&b;
        a=a^b;
        b=carry<<1;
    }
    printf("add(%d,%d):%d\n",c,d,a);

    temp=~d+1;  //take 2's complement of b and add it with a
    sub=c+temp;
    printf("diff(%d,%d):%d\n",c,d,temp);
    getch();
}

以下将起作用。

x - (-y)

Code to implement add,multiplication without using + , * operator;不使用+*运算符实现加法、乘法的代码; for subtraction pass 1's complement +1 of number to add function为减法传递数字的 1 的补码 +1 以add函数

#include<stdio.h>

unsigned int add(unsigned int x,unsigned int y)
{
         int carry=0;
    while (y != 0)
    {

        carry = x & y;  
        x = x ^ y; 
        y = carry << 1;
    }
    return x;
}
int multiply(int a,int b)
{
    int res=0;
    int i=0;
    int large= a>b ? a :b ;
    int small= a<b ? a :b ;
    for(i=0;i<small;i++)
    {
           res = add(large,res);                    
    }
    return res;
}
int main()
{
    printf("Sum :: %u,Multiply is :: %d",add(7,15),multiply(111,111));
    return 0;
}

This can be done recursively:这可以递归地完成:

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

    int sum = a ^ b; // add without carrying
    int carry = (a & b) << 1; // carry, but don’t add
    return add_without_arithm_recursively(sum, carry); // recurse
}

or iteratively:或迭代:

int add_without_arithm_iteratively(int a, int b)
{
    int sum, carry;

    do 
    {
        sum = a ^ b; // add without carrying
        carry = (a & b) << 1; // carry, but don’t add

        a = sum;
        b = carry;
    } while (b != 0);

    return a;
}

The question asks how to add two numbers so I don't understand why all the solutions offers the addition of two integers?该问题询问如何将两个数字相加,所以我不明白为什么所有解决方案都提供两个整数的相加? What if the two numbers were floats ie 2.3 + 1.8 are they also not considered numbers?如果这两个数字是浮点数,即2.3 + 1.8 ,它们也不被视为数字怎么办? Either the question needs to be revised or the answers.要么需要修改问题,要么需要修改答案。

For floats I believe the numbers should be broken into their components ie 2.3 = 2 + 0.3 then the 0.3 should be converted to an integer representation by multiplying with its exponent factor ie 0.3 = 3 * 10^-1 do the same for the other number and then add the integer segment using one of the bit shift methods given as a solution above handling situations for carry over to the unit digits location ie 2.7 + 3.3 = 6.0 = 2+3+0.7+0.3 = 2 + 3 + 7x10^-1 + 3x10^-1 = 2 + 3 + 10^10^-1 (this can be handled as two separate additions 2+3=5 and then 5+1=6 )对于浮点数,我相信数字应该分解成它们的组成部分,即2.3 = 2 + 0.3然后0.3应该通过乘以它的指数因子来转换为整数表示,即0.3 = 3 * 10^-1对另一个数字做同样的事情然后使用作为上述处理情况的解决方案之一给出的位移方法添加整数段以结转到单位数字位置,即2.7 + 3.3 = 6.0 = 2+3+0.7+0.3 = 2 + 3 + 7x10^-1 + 3x10^-1 = 2 + 3 + 10^10^-1 (这可以作为两个单独的加法处理2+3=5然后5+1=6

With given answers above, it can be done in single line code:有了上面给出的答案,它可以在单行代码中完成:

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

You can use double negetive to add two integers for example:您可以使用双负数来添加两个整数,例如:

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

Without using any operators adding two integers can be done in different ways as follows:不使用任何运算符将两个整数相加可以通过以下不同的方式完成:

int sum_of_2 (int a, int b){
   int sum=0, carry=sum;
   sum =a^b;
   carry = (a&b)<<1;
   return (b==0)? a: sum_of_2(sum, carry);
}
// Or you can just do it in one line as follows:
int sum_of_2 (int a, int b){
   return (b==0)? a: sum_of_2(a^b, (a&b)<<1);
}
// OR you can use the while loop instead of recursion function as follows
int sum_of_2 (int a, int b){
    if(b==0){
       return a;
   }
   while(b!=0){
     int sum = a^b;
     int carry = (a&b)<<1;
     a= sum;
     b=carry;
  }
  return a;
}
int add_without_arithmatic(int a, int b)
{
    int sum;
    char *p;
    p = (char *)a;
    sum = (int)&p[b];
    printf("\nSum : %d",sum);
}

I think this code would be helpful for add two numbers without plus operator 我认为这段代码对于添加两个没有加号运算符的数字会有所帮助

#include<stdio.h>

int main()

{
    int a, b, c;

    printf("enter two no. : ");
    scanf("%d%d", &a, &b);

    c = (a - ~b - 1);
    printf("%d\n", c);

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在不使用临时变量或算术运算的情况下交换两个数字? - How to swap two numbers without using temp variables or arithmetic operations? 不使用算术运算符的除法 - Division Without Using Arithmetic Operator 如何添加两个多维std :: vectors(不使用operator +)? - How to Add two multi-dimensional std::vectors (without using operator+)? 如何在不使用提取运算符的情况下计算txt文件中的数字数量? - How to count number of numbers in a txt file without using the extraction operator? C / C ++宏,用于在不使用三元运算符的情况下查找最多两个数字 - C/C++ Macro for finding maximum of two numbers without using ternary operator 使用运算符重载的两个复数之和 - Sum of two complex numbers using operator overloading 使用运算符重载对两个数字进行加法和减法 - addition and subtraction of two numbers using operator overloading 使用MFC加上两个数字 - Add two numbers using MFC 添加无符号数字而不使用&#39;+&#39;或&#39;++&#39; - Add unsigned numbers without using '+' or '++' 使用指针算法将两个数组的内容相加并保存到一个空数组 - Using pointer arithmetic to add the contents of two arrays and save to an empty array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM