É possível escrever um programa C que multiplique dois números sem usar os operadores de multiplicação e adição?
Encontrei isso no Stack Overflow . Por favor, ajude este pobre programador com seu problema. E por favor, não dê respostas como c = a/(1/((float)b))
, que é exatamente o mesmo que c = a*b
. (E já é dado como resposta.)
A resposta com mais votos em 19 de janeiro de 2014 vence.
Nota: Esta é uma pergunta de controle de código . Por favor, não leve a sério a pergunta e / ou respostas. Mais informações estão em trolling de código .
Respostas:
Sempre use recursão
Recusão é o caminho certo!
fonte
??::
sem parênteses, um para resolver o problema sem tentar ajustar as regras;)inc
função testa seu argumento para ver se o bit mais baixo é1
; nesse caso, ele se chama nos bits superiores restantes do argumento e retorna o resultado com o mesmo bit baixo que foi verificado0
, enquanto que, se não (ou seja, o bit mais baixo0
), substitui-o0
por a1
e retorna o resultado . O processo é muito semelhante ao que você faria se estivesse adicionando os valores manualmente, dígito binário por dígito binário.Você precisará compilar o programa toda vez, mas ele multiplicará qualquer número inteiro positivo exatamente em qualquer versão do C ou C ++.
fonte
"%zu"
formato string.sizeof(char[A][B])
irá funcionar (a menos que A <= 0 ou B <= 0 ou A * B overflows, caso em que você deve obter uma espécie 'tipo mau' de erro)main(){return sizeof(char[A][B]);}
e você compilar usandocc -DA=6 -DB=7 a.c; ./a.out; echo $?
Se você estiver bem com alguma imprecisão, poderá usar o método Monte Carlo :
Exemplo:
Eu acho que isso pode ser bom o suficiente;)
fonte
++
operador.-= -1
|= 1
(irá funcionar em 50% dos números, 100% do tempo)printf
incremento:printf("%*cc%n\n", count, &count, 'c');
(Imprime 'c' contar vezes, depois outro 'c' e armazena o número de caracteres escritos novamentecount
.Como você não especificou qual tamanho de número, presumo que você queira dizer dois números de um bit.
Se você deseja uma implementação maximamente eficiente, use a pequena implementação a seguir:
Observe que ele ainda aceita apenas bits, mesmo que os tipos sejam ints implícitos - requer menos código e, portanto, é mais eficiente. (E sim, ele compila.)
fonte
return a && b;
. É mais curto, então é mais rápido.return a&b;
.#include<stdbool.h>
que definirtrue
efalse
.#include<stdbool.h>
parece ser apenas três#define
s que você pode fazer a si mesmo (true
,false
,bool
, e uma bandeira para marcar que ele tenha sido ativado). Você também pode usar um truque de uma das outras respostas e usar o implícitoint
para a versão "curta".Aqui está um script de shell simples para fazer isso:
UPDATE: É claro que, para fazê-lo em C, basta envolvê-lo
exec("bash", "-c", ...)
. (Obrigado, AmeliaBR)fonte
%20
para evitar o uso de quaisquer+
sinais.) Mas você ainda precisa analisar a saída (em C) para obter o valor dela. O que será especialmente complicado, pois a saída parece ser uma imagem, não texto. A análise de HTML e o OCR podem ser a melhor resposta possível para esse problema.Por que, vamos fazer uma pesquisa pela metade recursiva entre INT64_MIN e INT64_MAX!
PS Será feliz sigsegv com alguns valores. ;)
fonte
Infelizmente, isso funciona apenas para números inteiros.
Como a adição é proibida, vamos criar um operador de incremento primeiro:
Em seguida, temos que lidar com o sinal. Primeiro, encontre o bit do sinal:
Então pegue o sinal e a magnitude de cada argumento. Para negar um número no complemento de dois, inverta todos os bits e adicione um.
Para multiplicar dois números inteiros positivos, podemos usar o significado geométrico da multiplicação:
trolls:
a++
realmente conta como adição? Aposto que o professor pretendia permitir.<<
é, na verdade, multiplicação por uma potência de dois, portanto, tecnicamente, isso não deve ser permitido.-1
não é a melhor maneira de encontrar o bit de sinal. Mesmo se não houvesse constante interna, você poderia fazer um deslocamento lógico para a direita de -1 e inverter todos os bits.MIN_INT
(AKAsignBit
) é negativo, isso quebra para esse valor. Felizmente, ele ainda funciona na metade dos casos, porqueMIN_INT * [even number]
deve ser zero.Além disso,plusOne
interrompe-1
, causando loops infinitos sempre que o resultado exceder o limite.plusOne
funciona muito bem para qualquer valor. Desculpe pela confusão.fonte
(x ^ y) | ((x & y) << 1)
não funciona muito bem, não vai propagar carry quando x ou y e realizar são verdadeiras na mesma posição :)Também funciona para números de ponto flutuante:
fonte
Todo mundo sabe que o Python é mais fácil de usar que o C. E o Python tem funções correspondentes a todos os operadores, para casos em que você não pode usá-lo. Qual é exatamente a nossa definição de problema, certo? Assim:
fonte
Nenhuma das outras respostas é teoricamente correta. Como o primeiro comentário sobre a questão diz:
Precisamos definir multiplicação e números antes que uma resposta seja possível. Quando o fazemos, o problema se torna trivial.
A maneira mais popular de fazer isso no início da lógica matemática é construir ordinais de von Neumann sobre a teoria dos conjuntos ZF e, em seguida, usar os axiomas Peano .
Isso se traduz naturalmente em C, assumindo que você tenha um tipo de conjunto que pode conter outros conjuntos. Ele não precisa conter nada além de conjuntos, o que o torna trivial (nada disso faz
void*
disparates na maioria das bibliotecas de conjuntos); portanto, deixarei a implementação como um exercício para o leitor.Então, primeiro:
Se você quiser expandir isso para números inteiros, racionais, reais, surreals, etc., poderá - com precisão infinita (supondo que você tenha memória e CPU infinitas), para inicializar. Mas, como disse Kroenecker, Deus fez os números naturais; todo o resto é obra do homem, então realmente, por que se preocupar?
fonte
Se você considera o truque a [b] uma trapaça (já que é realmente um complemento), isso funciona. Mas as pesquisas de tabela também envolvem acréscimos de ponteiro.
Veja http://en.wikipedia.org/wiki/IBM_1620 - um computador que realmente fez adição usando tabelas de pesquisa ...
Algo satisfatório sobre o uso de um mecanismo de tabela para 'acelerar' uma operação que poderia realmente ser realizada em uma instrução.
fonte
*
char (embora não seja a multiplicação)Não sei ao certo o que constitui "trapaça" nessas postagens de "troll de código", mas isso multiplica 2 números inteiros arbitrários, em tempo de execução, sem operador
*
ou+
usando bibliotecas padrão (C99).fonte
Minha solução troll para
unsigned int
:fonte
Existem muitas respostas boas aqui, mas não parece que muitas delas tirem vantagem do fato de que os computadores modernos são realmente poderosos. Existem várias unidades de processamento na maioria das CPUs, então por que usar apenas uma? Podemos explorar isso para obter ótimos resultados de desempenho.
Aqui está um exemplo de seu uso:
A
#pragma omp parallel
diretiva faz com que o OpenMP divida cada parte do loop for em uma unidade de execução diferente, por isso estamos multiplicando em paralelo!Observe que você precisa usar o
-fopenmp
sinalizador para dizer ao compilador para usar o OpenMP.Peças de pesca à corrica:
for
loop - cada thread executa o loop.answer--
; na maioria das vezes, ele não aparece, mas ocasionalmente causa resultados imprecisos.fonte
Infelizmente, a multiplicação é um problema muito difícil na ciência da computação. A melhor solução é usar a divisão:
fonte
Na vida real, eu geralmente respondo a trollar com conhecimento, então aqui está uma resposta que nem trolla. Funciona para todos os
int
valores, tanto quanto eu posso ver.Isto é, até onde eu entendi, muito parecido com o modo como uma CPU pode realmente fazer a multiplicação de números inteiros. Primeiro, garantimos que pelo menos um dos argumentos (
a
) seja positivo, lançando o sinal em ambos sea
for negativo (e não, eu me recuso a contar a negação como um tipo de adição ou multiplicação). Em seguida, owhile (a)
loop adiciona uma cópia deslocadab
do resultado para cada bit definidoa
. Odo
loop implementa or += x
uso e, xor e a mudança no que é claramente um conjunto de semi-somadores, com os bits de transporte alimentadosx
até que não haja mais (uma CPU real usaria somadores completos, o que é mais eficiente, mas C não ' não temos os operadores necessários para isso, a menos que você conte o+
operador).fonte
while(a)
loop nunca termina.fonte
while(C/A != B || C%A)
:?Jogando isso na mistura:
Na página de informações .
- Introduzir algo extremamente inaceitável ou irracional no código que não pode ser removido sem jogar tudo fora, tornando a resposta totalmente inútil para o OP.
- [...] A intenção é fazer a lição de casa em um idioma que o OP preguiçoso possa achar aceitável, mas ainda o frustre.
fonte
fonte
Certo:
Mas é claro que isso é trapaça; obviamente ele quer ser capaz de fornecer dois números, certo?
fonte
Não há aritmética como a aritmética de ponteiros:
A função
f
implementa multiplicação.main
simplesmente chama isso com dois argumentos.Funciona para números negativos também.
fonte
a
, sim, negativo,b
acho que não. Mas isso pode ser corrigido de várias maneiras criativas. Mais simples seria sign_a ^ = sign_b, sign_b = 0.C #
Eu acho que subtração e negação não são permitidas ... Enfim:
fonte
C com intrínsecas SSE (porque tudo está melhor com o SIMD):
A grande vantagem dessa implementação é que ela pode ser facilmente adaptada para realizar 4 multiplicações paralelas sem
*
ou+
se necessário.fonte
fonte
strlen(cg) != a
é um método muito difícil de eliminar o--
(torna O (N * N)).Provavelmente rápido demais :-(
fonte
Essa versão do Haskell funciona apenas com números inteiros não negativos, mas faz a multiplicação da maneira que as crianças aprendem primeiro. Ou seja, 3x4 é 3 grupos de 4 coisas. Nesse caso, as "coisas" sendo contadas são entalhes ('|') em um pedaço de pau.
fonte
Isso pode funcionar em C99, se o tempo estiver bom, e seu compilador oferecer suporte a bobagens indefinidas.
fonte
Como o OP não pediu C , aqui está um no SQL (Oracle)!
fonte
*
s!Pode conter vestígios de UD.
fonte
Execução de teste:
fonte