Dados dos enteros a y b, ¿cómo podemos evaluar la suma a + b sin utilizar operadores como +, -, ++, –,…?
Una forma interesante sería:
CPP
// May not work with C++ compilers and // may produce warnings in C. // Returns sum of 'a' and 'b' int sum(int a, int b) { char *p = a; return (int)&p[b]; }
A pesar de su incomodidad a primera vista, podemos entender fácilmente lo que está sucediendo. Primero, creamos un puntero p. El valor de un puntero es una dirección de memoria. En este caso, el valor de p es la dirección a.Recuerda: p apunta a la posición a. En ese ejemplo, si queremos saber el valor de la posición a (999) le preguntamos a *p. Si queremos saber la dirección de la variable a (41), le preguntamos a &a. Si evaluamos p[b], obtendríamos el valor de la memoria en la posición p + b. De hecho, evaluamos &p[b], que es lo mismo que obtener la dirección p + b sin acceder a su valor. Como p = a, &p[b] devolverá la dirección a + b. No queremos devolver una dirección de memoria (int*). Queremos devolver un número entero (int). Entonces, convertimos &p[b] a int. ¿Qué pasa si cambiamos el tipo de p de char* a int*? Permítanme arreglar lo que dije antes: cuando evaluamos p[b] no evaluamos p + b. Evaluamos p + sizeof(*p) * b. ¿Por qué? Imagine este ejemplo: las variables de tipo int ocupan cuatro posiciones en la memoria.Este sizeof(*p) considera la cantidad de posiciones que ocupa cada variable en la memoria. Queremos evaluar p + b. En otras palabras, queremos que sizeof(*p) sea igual a 1. En consecuencia, si *p es un carácter, estamos contentos.
Miremos la tabla de verdad de la suma (perdonen el acarreo por ahora): Mirando con atención, notamos que la tabla de verdad de la suma y la de xor son las mismas. Es 1 solo cuando la entrada es diferente. Ahora bien, ¿cómo podemos detectar el carry? Veamos la tabla de verdad del acarreo. Mirando cuidadosamente, notamos que las tablas de verdad de la suma y xor son las mismas. Es 1 solo cuando la entrada es diferente. Ahora bien, ¿cómo podemos detectar el carry? Veamos la tabla de verdad del acarreo. Mirando cuidadosamente una vez más, notamos que las tablas de verdad del acarreo y del and lógico son idénticas. Ahora, tenemos que desplazar a & 1 a la izquierda y sumar con a ^ b. Sin embargo, estas operaciones también pueden tener acarreos. No hay problema, simplemente sume a ^ b con a & 1 desplazados a la izquierda recursivamente.
CPP
// Returns sum of a and b using bitwise // operators. int sum(int a, int b) { int s = a ^ b; int carry = a & b; if (carry == 0) return s; else return sum(s, carry << 1); }
Esta solución ha sido discutida aquí .
Recordemos algunos datos:
- El printf devuelve el número de caracteres impresos con éxito.
- El especificador %*c solicita dos parámetros: el primero es el ancho personalizado y el segundo es el carácter. Por ejemplo, printf(“%*c”, 5, ‘a’) imprimirá ” a”.
- El carácter especial ‘\r’ devuelve el cursor desde el principio de la string de salida. Por ejemplo, printf(“abcd\r12”) imprimirá “12cd”.
Teniendo esto en cuenta, podemos entender esta función:
CPP
// Returns sum of a and b using printf // Constraints: a, b > 0. int sum(int a, int b) { return printf("%*c%*c", a, '\r', b, '\r'); }
Esta solución ha sido discutida aquí . Este artículo es una contribución de Igor Carpanese . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo y enviarlo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA