¿Es posible escribir un programa en C que multiplique dos números sin usar los operadores de multiplicación y suma?
Encontré esto en Stack Overflow . Por favor, ayuda a este pobre programador con su problema. Y por favor no dé respuestas como c = a/(1/((float)b))
, que es exactamente lo mismo que c = a*b
. (Y ya se da como respuesta).
La respuesta con más votos a favor el 19 de enero de 2014 gana.
Nota: Esta es una pregunta de arrastre de código . No tome en serio la pregunta y / o las respuestas. Más información está en código trolling .
Respuestas:
Siempre usa la recursividad
Recusion es la forma correcta!
fuente
??::
sin paréntesis, uno para resolver el problema sin tratar de modificar las reglas;)inc
función prueba su argumento para ver si el bit más bajo es1
; si es así, se llama a sí mismo en los bits superiores restantes del argumento y devuelve el resultado con el mismo bit bajo que se verificó establecido0
, mientras que si no (es decir, el bit más bajo es0
), reemplaza eso0
con1
ay devuelve el resultado . El proceso es muy similar a lo que haría si estuviera agregando los valores a mano, dígito binario por dígito binario.Tendrá que compilar el programa cada vez, pero multiplica todos los enteros positivos exactamente en cualquier versión de C o C ++.
fuente
"%zu"
cadena de formato.sizeof(char[A][B])
funcionará (a menos que A <= 0 o B <= 0 o A * B se desborde, en cuyo caso debería obtener un tipo de error de 'tipo malo')main(){return sizeof(char[A][B]);}
y compilarlo usandocc -DA=6 -DB=7 a.c; ./a.out; echo $?
Si está de acuerdo con un poco de imprecisión, puede usar el método Monte Carlo :
Ejemplo:
Supongo que esto podría ser lo suficientemente bueno;)
fuente
++
operador.-= -1
|= 1
(funcionará en el 50% de los números, el 100% del tiempo)printf
incremento:printf("%*cc%n\n", count, &count, 'c');
(Imprime 'c' veces, luego otra 'c', y almacena el número de caracteres escritos nuevamentecount
.Como no especificó qué tamaño de número, supongo que se refiere a dos números de un bit.
Si desea una implementación de máxima eficiencia, use la siguiente implementación pequeña:
Tenga en cuenta que todavía solo acepta bits aunque los tipos son ints implícitos: requiere menos código y, por lo tanto, es más eficiente. (Y sí, se compila).
fuente
return a && b;
. Es más corto, por lo que es más rápido.return a&b;
.#include<stdbool.h>
que definirtrue
yfalse
.#include<stdbool.h>
parece ser sólo tres#define
s que usted puede hacer usted mismo (true
,false
,bool
, y una bandera para señalar que ha sido activada). También puede tomar un truco de una de las otras respuestas y usarlo implícitoint
para la versión "corta".Aquí hay un script de shell simple para hacerlo:
ACTUALIZACIÓN: Por supuesto, para hacerlo en C, solo envuélvelo
exec("bash", "-c", ...)
. (Gracias, AmeliaBR)fuente
%20
para evitar el uso de+
signos). Pero aún necesita analizar la salida (en C) para obtener el valor. Lo cual será especialmente complicado, ya que el resultado parece ser una imagen, no un texto. El análisis de HTML más OCR podría ser la mejor respuesta posible a este problema.¡Por qué, hagamos una búsqueda a la mitad recursiva entre INT64_MIN e INT64_MAX!
PD: felizmente firmará con algunos valores. ;)
fuente
Desafortunadamente, esto solo funciona para enteros.
Como la adición no está permitida, creemos primero un operador de incremento:
A continuación, tenemos que manejar la señal. Primero, encuentre el bit de signo:
Luego tome el signo y la magnitud de cada argumento. Para negar un número en el complemento de dos, invierta todos los bits y agregue uno.
Para multiplicar dos enteros positivos, podemos usar el significado geométrico de la multiplicación:
trolls:
a++
realmente cuenta como adición? Apuesto a que el maestro tenía la intención de permitirlo.<<
es en realidad la multiplicación por una potencia de dos, por lo que técnicamente no se debe permitir.-1
no es la mejor manera de encontrar el bit de signo. Incluso si no hubiera una constante incorporada, podría hacer un cambio lógico a la derecha de -1 y luego invertir todos los bits.MIN_INT
(AKAsignBit
) es negativo, esto se rompe para ese valor. Afortunadamente, todavía funciona en la mitad de los casos, porqueMIN_INT * [even number]
debería ser cero.Además, seplusOne
rompe para-1
causar bucles infinitos cada vez que el resultado se desborda.plusOne
funciona bien para cualquier valor. Perdón por la confusion.fuente
(x ^ y) | ((x & y) << 1)
no funciona del todo, no propagará carry cuando x o y y carry sean verdaderas en la misma posición :)Funciona también para números de coma flotante:
fuente
Todo el mundo sabe que Python es más fácil de usar que C. Y Python tiene funciones correspondientes a cada operador, en los casos en que no puede usar el operador. ¿Cuál es exactamente nuestra definición del problema, verdad? Entonces:
fuente
Ninguna de las otras respuestas es teóricamente sólida. Como dice el primer comentario sobre la pregunta:
Necesitamos definir la multiplicación y los números, incluso antes de que sea posible una respuesta. Una vez que lo hacemos, el problema se vuelve trivial.
La forma más popular de hacer esto al comenzar la lógica matemática es construir ordinales de von Neumann sobre la teoría de conjuntos ZF , y luego usar los axiomas de Peano .
Esto se traduce naturalmente en C, suponiendo que tenga un tipo de conjunto que pueda contener otros conjuntos. No tiene que contener nada más que conjuntos, lo que lo hace trivial (nada de eso
void*
sin sentido en la mayoría de las bibliotecas de conjuntos), por lo que dejaré la implementación como un ejercicio para el lector.Entonces, primero:
Si desea expandir esto a enteros, racionales, reales, surrealistas, etc., puede arrancar con una precisión infinita (suponiendo que tenga memoria y CPU infinitas). Pero como dijo Kroenecker, Dios hizo los números naturales; todo lo demás es obra del hombre, así que realmente, ¿por qué molestarse?
fuente
Si considera que el truco a [b] es una trampa (ya que es realmente un complemento), entonces esto funciona en su lugar. Pero las búsquedas de tablas también incluyen punteros añadidos.
Ver http://en.wikipedia.org/wiki/IBM_1620 , una computadora que realmente hizo la suma usando tablas de búsqueda ...
Algo satisfactorio sobre el uso de un mecanismo de tabla para 'acelerar' una operación que en realidad podría hacerse en una sola instrucción.
fuente
*
char (aunque no es multiplicación)No estoy seguro de qué constituye "trampa" en estas publicaciones de "código troll", pero esto multiplica 2 enteros arbitrarios, en tiempo de ejecución, sin operador
*
o+
utilizando bibliotecas estándar (C99).fuente
Mi solución troll para
unsigned int
:fuente
Aquí hay muchas buenas respuestas, pero no parece que muchas de ellas aprovechen el hecho de que las computadoras modernas son realmente poderosas. Hay múltiples unidades de procesamiento en la mayoría de las CPU, entonces, ¿por qué usar solo una? Podemos explotar esto para obtener excelentes resultados de rendimiento.
Aquí hay un ejemplo de su uso:
La
#pragma omp parallel
directiva hace que OpenMP divida cada parte del ciclo for en una unidad de ejecución diferente, ¡así que estamos multiplicando en paralelo!Tenga en cuenta que debe usar el
-fopenmp
indicador para indicarle al compilador que use OpenMP.Troll partes:
for
bucle: cada subproceso ejecuta el bucle.answer--
; la mayoría de las veces, no aparecerá, pero ocasionalmente causará resultados inexactos.fuente
Desafortunadamente, la multiplicación es un problema muy difícil en informática. La mejor solución es usar la división en su lugar:
fuente
En la vida real, generalmente respondo al trolling con conocimiento, así que aquí hay una respuesta que no trolló en absoluto. Funciona para todos los
int
valores hasta donde puedo ver.A mi entender, esto es muy parecido a cómo una CPU podría hacer multiplicación de enteros. Primero, nos aseguramos de que al menos uno de los argumentos (
a
) sea positivo volteando el signo en ambos sia
es negativo (y no, me niego a contar la negación como un tipo de suma o multiplicación). Luego, elwhile (a)
bucle agrega una copia desplazada deb
al resultado para cada bit establecidoa
. Eldo
bucle implementa elr += x
uso y, xor y el cambio en lo que claramente es un conjunto de medios sumadores, con los bits de arrastre retroalimentadosx
hasta que no haya más (una CPU real usaría sumadores completos, lo que es más eficiente, pero C no lo hace) No tenga los operadores que necesitamos para esto, a menos que cuente el+
operador).fuente
while(a)
ciclo nunca termina.fuente
while(C/A != B || C%A)
:?Lanzando esto a la mezcla:
De la página de información .
- Introducir algo extremadamente inaceptable o irrazonable en el código que no se puede eliminar sin tirar todo, lo que hace que la respuesta sea completamente inútil para el OP.
- [...] La intención es hacer la tarea en un idioma que el OP perezoso podría considerar aceptable, pero aún así frustrarlo.
fuente
fuente
Seguro:
Pero, por supuesto, eso es trampa; obviamente quiere poder suministrar dos números, ¿verdad?
fuente
No hay aritmética como la aritmética de puntero:
La función
f
implementa la multiplicación.main
simplemente lo llama con dos argumentos.Funciona para números negativos también.
fuente
a
, sí, negativob
, no lo creo. Pero eso se puede solucionar de muchas maneras creativas. Más simple sería sign_a ^ = sign_b, sign_b = 0.C#
Creo que la resta y la negación no están permitidas ... De todos modos:
fuente
C con intrínsecos SSE (porque todo es mejor con SIMD):
La gran ventaja de esta implementación es que se puede adaptar fácilmente para realizar 4 multiplicaciones paralelas sin
*
o+
si es necesario.fuente
fuente
strlen(cg) != a
es un método muy trolling para eliminar el--
(lo hace O (N * N)).Probablemente demasiado rápido :-(
fuente
Esta versión de Haskell solo funciona con enteros no negativos, pero multiplica la forma en que los niños la aprenden por primera vez. Es decir, 3x4 es 3 grupos de 4 cosas. En este caso, las "cosas" que se cuentan son muescas ('|') en un palo.
fuente
Esto puede funcionar en C99, si hace buen tiempo, y su compilador admite tonterías indefinidas.
fuente
Como el OP no solicitó C , ¡aquí hay uno en (Oracle) SQL!
fuente
*
s!Puede contener trazas de UD.
fuente
Prueba de funcionamiento:
fuente