Cómo agregar dos números sin usar ++ o + u otro operador aritmético

¿Cómo agrego dos números sin usar ++ o + o cualquier otro operador aritmético?

Fue una pregunta hecha hace mucho tiempo en alguna entrevista en el campus. De todos modos, hoy alguien hizo una pregunta con respecto a algunas manipulaciones de bits, y en las respuestas se refirió a un hermoso tipo de Stanford bit twiding. Pasé algún tiempo estudiándolo y pensé que realmente podría haber una respuesta a la pregunta. No lo sé, no pude encontrar uno. ¿Existe una respuesta?

Esto es algo que escribí hace un tiempo por diversión. Utiliza una representación complementaria de dos e implementa la adición mediante cambios repetidos con un bit de acarreo, implementando otros operadores principalmente en términos de sum.

#include  /* atoi() */ #include  /* (f)printf */ #include  /* 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; } 

O, en lugar del enfoque bit a bit de Jason, puede calcular muchos bits en paralelo, esto debería ejecutarse mucho más rápido con números grandes. En cada paso, determine la parte portadora y la parte que es sum. Intenta agregar el acarreo a la sum, lo que podría causar que se cargue nuevamente, de ahí el bucle.

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

cuando sums 1 y 3, ambos números tienen el bit 1 establecido, por lo que la sum de ese 1 + 1 se transmite. El siguiente paso agrega 2 a 2 y eso lleva a la sum correcta cuatro. Eso causa una salida

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

O un ejemplo más complejo

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

Editar: para que funcione fácilmente en los números con signo, debe introducir un límite superior en a y 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 

Intentalo

 add(-1, 1) 

ver un solo bit llevar a través de todo el rango y desbordar más de 32 iteraciones

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

Podrías transformar un circuito sumdor en un algoritmo. Solo hacen operaciones bit a bit =)

Bueno, implementar un equivalente con operadores booleanos es bastante simple: haces una sum bit por bit (que es un XOR), con carry (que es un AND). Me gusta esto:

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

Ya has obtenido un par de respuestas de manipulación. Aquí hay algo diferente.

En C, arr[ind] == *(arr + ind) . Esto nos permite hacer cosas ligeramente confusas (pero legales) como int arr = { 3, 1, 4, 5 }; int val = 0[arr]; int arr = { 3, 1, 4, 5 }; int val = 0[arr]; .

Así que podemos definir una función de adición personalizada (sin el uso explícito de un operador aritmético) así:

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

Alternativamente, si queremos evitar este truco, y si por operador aritmético incluyen | , & y ^ (para que no se permita la manipulación directa de bits), podemos hacerlo a través de la tabla de búsqueda:

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

Todas las operaciones aritméticas se descomponen en operaciones bit a bit para ser implementadas en electrónica, usando compuertas NAND, AND, OR, etc.

La composición de Adder se puede ver aquí .

Para números sin signo, utilice el mismo algoritmo de sum que aprendió en primera clase, pero para la base 2 en lugar de la base 10. Ejemplo para 3 + 2 (base 10), es decir, 11 + 10 en la base 2:

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

Si te sientes cómico, siempre existe este enfoque espectacularmente horrible para agregar dos enteros sin signo (relativamente pequeños). No hay operadores aritméticos en ningún lugar de tu código.

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

En C, usando stdio (reemplace snprintf con _snprintf en los comstackdores de Microsoft):

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

Aquí hay una solución C compacta. A veces, la recursividad es más legible que los bucles.

 int add(int a, int b){ if (b == 0) return a; return add(a ^ b, (a & b) < < 1); } 
 #include 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; } 
 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; } 
 ## to add or subtract without using '+' and '-' ## #include #include #include 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(); } 

Lo siguiente funcionaría.

 x - (-y) 

Esto puede hacerse recursivamente:

 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 } 

o iterativamente

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

Código para implementar agregar, multiplicar sin usar el operador + , * ; para la resta, pase el complemento 1 +1 del número para add función

 #include 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 

La pregunta pregunta cómo agregar dos números, por lo que no entiendo por qué todas las soluciones ofrecen la sum de dos enteros. ¿Qué pasa si los dos números son flotantes, es decir, 2.3 + 1.8 ¿tampoco se consideran números? O la pregunta necesita ser revisada o las respuestas.

Para flotadores, creo que los números deben dividirse en sus componentes, es decir, 2.3 = 2 + 0.3 entonces el 0.3 debe convertirse a una representación entera al multiplicar con su factor exponente, es decir, 0.3 = 3 * 10^-1 hacer lo mismo con el otro número y luego agregue el segmento entero utilizando uno de los métodos de cambio de bit dados como una solución sobre situaciones de manejo para transferir a la ubicación de los dígitos de la unidad, es decir 2.7 + 3.3 = 6.0 = 2+3+0.7+0.3 = 2 + 3 + 7x10^-1 + 3x10^-1 = 2 + 3 + 10^10^-1 (esto se puede manejar como dos adiciones separadas 2+3=5 y luego 5+1=6 )

 int add_without_arithmatic(int a, int b) { int sum; char *p; p = (char *)a; sum = (int)&p[b]; printf("\nSum : %d",sum); } 

Con las respuestas dadas anteriormente, se puede hacer en código de una sola línea:

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

Creo que este código sería útil para agregar dos números sin el operador plus

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