Est-il possible d'écrire un programme en langage C qui multiplie deux nombres sans utiliser les opérateurs de multiplication et d'addition?
J'ai trouvé ceci sur Stack Overflow . S'il vous plaît aider ce pauvre programmeur avec son problème. Et s'il vous plaît ne donnez pas de réponses comme c = a/(1/((float)b))
, ce qui est exactement la même chose que c = a*b
. (Et est déjà donné comme réponse.)
La réponse avec le plus de votes positifs le 19 janvier 2014 est la victoire.
Remarque: il s'agit d'une question à la traîne de code . S'il vous plaît ne prenez pas la question et / ou les réponses au sérieux. Plus d'informations sont en code-trolling .
Réponses:
Toujours utiliser la récursivité
La recusion est la bonne façon!
la source
??::
sans parenthèses, un pour résoudre le problème sans essayer d'affiner les règles;)inc
fonction teste son argument pour voir si le bit le plus bas est1
; si tel est le cas, il s’appelle lui-même sur les bits supérieurs restants de l’argument et renvoie le résultat avec le même bit faible vérifié0
, alors que si ce n’est pas le cas (c’est-à-dire que le bit le plus bas est0
), il le remplace0
par un1
et renvoie le résultat. . Le processus est très similaire à ce que vous feriez si vous ajoutiez les valeurs à la main, chiffre binaire par chiffre binaire.Vous devrez compiler le programme à chaque fois, mais il multiplie tous les entiers positifs exactement dans toutes les versions de C ou C ++.
la source
"%zu"
chaîne de format.sizeof(char[A][B])
fonctionnera (sauf si A <= 0 ou B <= 0 ou A * B déborde, auquel cas vous devriez obtenir une erreur de type "mauvais type")main(){return sizeof(char[A][B]);}
et compiler aveccc -DA=6 -DB=7 a.c; ./a.out; echo $?
Si vous êtes OK avec un peu d'imprécision, vous pouvez utiliser la méthode de Monte Carlo :
Exemple:
Je suppose que cela pourrait suffire;)
la source
++
opérateur.-= -1
|= 1
(travaillera sur 50% des chiffres, 100% du temps)printf
incréments:printf("%*cc%n\n", count, &count, 'c');
(Prints 'c' compter le nombre de fois, puis un autre 'c', et stocker le nombre de caractères écritscount
.Puisque vous n'avez pas précisé la taille du nombre, je suppose que vous voulez dire deux nombres d'un bit.
Si vous souhaitez une implémentation extrêmement efficace, utilisez la minuscule implémentation suivante:
Notez qu'il n'accepte toujours que les bits, même si les types sont des enttes implicites - il prend moins de code et est donc plus efficace. (Et oui, ça compile.)
la source
return a && b;
. C'est plus court, donc c'est plus rapide.return a&b;
.#include<stdbool.h>
définirtrue
etfalse
.#include<stdbool.h>
semble être juste trois#define
s que vous pouvez faire vous - même (true
,false
,bool
et un drapeau pour marquer qu'il a été activé). Vous pouvez également utiliser une astuce d’une autre réponse et utiliser implicitementint
la version "courte".Voici un script shell simple pour le faire:
UPDATE: Bien sûr, pour le faire en C, emballez-le simplement
exec("bash", "-c", ...)
. (Merci, AmeliaBR)la source
%20
pour éviter d’utiliser des+
signes.) Mais vous devez quand même analyser la sortie (en C) pour en extraire la valeur. Ce qui sera particulièrement délicat, car la sortie semble être une image, pas un texte. L'analyse HTML plus l'OCR pourrait en faire la meilleure réponse possible à ce problème.Pourquoi, effectuons une recherche récursive en divisant par deux entre INT64_MIN et INT64_MAX!
Post-scriptum Il va sigsegv heureusement avec certaines valeurs. ;)
la source
Malheureusement, cela ne fonctionne que pour les entiers.
Puisque l'addition est interdite, construisons d'abord un opérateur d'incrémentation:
Ensuite, nous devons gérer le signe. D'abord, trouvez le bit de signe:
Ensuite, prenez le signe et la magnitude de chaque argument. Pour annuler un nombre dans un complément à deux, inversez tous les bits et ajoutez un.
Pour multiplier deux entiers positifs, nous pouvons utiliser la signification géométrique de multiplication:
trolls:
a++
vraiment comme une addition? Je parie que le professeur avait l'intention de le permettre.<<
est en fait la multiplication par une puissance de deux, il devrait donc être techniquement interdit.-1
n'est pas la meilleure façon de trouver le bit de signe. Même s'il n'y avait pas de constante intégrée, vous pourriez effectuer un décalage logique à droite de -1, puis inverser tous les bits.MIN_INT
(AKAsignBit
) est négative, cela se brise pour cette valeur. Heureusement, cela fonctionne toujours dans la moitié des cas, carMIN_INT * [even number]
devrait être nul.En outre,plusOne
rompt pour-1
, provoquant des boucles infinies chaque fois que le résultat déborde.plusOne
fonctionne très bien pour n'importe quelle valeur. Désolé pour la confusion.la source
(x ^ y) | ((x & y) << 1)
ne fonctionne pas tout à fait, il ne se propagera pas lorsque x ou y et que carry sont tous deux vrais dans la même position :)Fonctionne également pour les nombres à virgule flottante:
la source
Tout le monde sait que Python est plus facile à utiliser que C. Et Python a des fonctions correspondant à chaque opérateur, dans les cas où vous ne pouvez pas utiliser l'opérateur. Quelle est exactement notre définition du problème, non? Alors:
la source
Aucune des autres réponses n'est théoriquement valable. Comme le dit le tout premier commentaire sur la question:
Nous devons définir la multiplication et les nombres avant même de pouvoir obtenir une réponse. Une fois que nous le faisons, le problème devient trivial.
Le moyen le plus populaire de faire cela en commençant la logique mathématique consiste à construire des ordinaux de von Neumann sur la théorie des ensembles ZF , puis à utiliser les axiomes de Peano .
Cela se traduit naturellement en C, en supposant que vous ayez un type de jeu pouvant contenir d'autres jeux. Il ne doit pas contenir quoi que ce soit , mais des ensembles, ce qui le rend trivial (aucun de cette coulée
void*
non - sens dans la plupart des bibliothèques set), donc je vais laisser la mise en œuvre comme un exercice pour le lecteur.Alors, d'abord:
Si vous souhaitez étendre cela aux entiers, aux rationnels, aux réels, aux surréels, etc., vous pouvez — avec une précision infinie (en supposant que vous avez une mémoire infinie et un processeur), de démarrer. Mais comme Kroenecker l'a dit, Dieu a créé les nombres naturels; tout le reste est le travail de l'homme, alors vraiment, pourquoi s'embêter?
la source
Si vous considérez que le hack a [b] est une triche (puisqu'il s'agit vraiment d'un ajout), cela fonctionne à la place. Mais les recherches dans les tables impliquent également un ajout de pointeur.
Voir http://en.wikipedia.org/wiki/IBM_1620 - un ordinateur qui a effectivement ajouté des données à l'aide de tables de recherche ...
Quelque chose de satisfaisant à propos de l'utilisation d'un mécanisme de table pour «accélérer» une opération qui pourrait réellement être effectuée en une seule instruction.
la source
*
(bien que ce ne soit pas une multiplication)Je ne suis pas sûr de ce qui constitue une "triche" dans ces publications "code troll", mais cela multiplie 2 entiers arbitraires, au moment de l'exécution, sans opérateur
*
ou+
utilisant des bibliothèques standard (C99).la source
Ma solution troll pour
unsigned int
:la source
Il y a beaucoup de bonnes réponses ici, mais il ne semble pas que beaucoup d'entre elles tirent parti du fait que les ordinateurs modernes sont vraiment puissants. Il existe plusieurs unités de traitement dans la plupart des processeurs, alors pourquoi en utiliser une seule? Nous pouvons exploiter cela pour obtenir d'excellents résultats.
Voici un exemple de son utilisation:
La
#pragma omp parallel
directive oblige OpenMP à diviser chaque partie de la boucle for en une unité d'exécution différente, nous nous multiplions donc en parallèle!Notez que vous devez utiliser l'
-fopenmp
indicateur pour indiquer au compilateur d'utiliser OpenMP.Troll parties:
for
boucle - chaque thread exécute la boucle.answer--
; la plupart du temps, il n'apparaîtra pas, mais occasionnellement, il provoquera des résultats inexacts.la source
Malheureusement, la multiplication est un problème très difficile en informatique. La meilleure solution consiste à utiliser la division à la place:
la source
Dans la vraie vie, je réponds habituellement à la traîne par la connaissance, alors voici une réponse qui ne traine pas du tout. Cela fonctionne pour toutes les
int
valeurs dans la mesure où je peux voir.À ma connaissance, cela ressemble beaucoup à la façon dont un processeur peut en fait multiplier des nombres entiers. Premièrement, nous nous assurons qu'au moins un des arguments (
a
) soit positif en retournant le signe sia
est négatif (et non, je refuse de compter la négation comme une sorte d'addition ou de multiplication). Ensuite, lawhile (a)
boucle ajoute une copie décalée deb
au résultat pour chaque bit défini dansa
. Lado
boucle implémente l'r += x
utilisation de et, xor et transforme ce qui est clairement un ensemble de demi-additionneurs, avec les bits de report renvoyésx
jusqu'à ce qu'il n'y en ait plus (un processeur réel utiliserait des additionneurs complets, ce qui est plus efficace, mais C t ont les opérateurs dont nous avons besoin pour cela, à moins que vous ne les comptiez+
).la source
while(a)
boucle ne se termine jamais.la source
while(C/A != B || C%A)
?Jeter ceci dans le mélange:
De la page d'information .
- Introduire dans le code quelque chose d'extrêmement inacceptable ou déraisonnable qui ne peut pas être supprimé sans tout jeter, ce qui rend la réponse totalement inutile pour le PO.
- […] L'intention est de faire les devoirs dans une langue que le PO paresseux pourrait juger acceptable, mais qui le frustre encore.
la source
la source
Sûr:
Mais bien sûr, c'est de la triche. il veut évidemment pouvoir _soumettre) deux nombres, non?
la source
Il n'y a pas d'arithmétique comme l'arithmétique de pointeur:
La fonction
f
implémente la multiplication.main
l'appelle simplement avec deux arguments.Fonctionne aussi pour les nombres négatifs.
la source
a
, oui, négatif,b
je ne le pense pas. Mais c'est réparable de nombreuses manières créatives. Le plus simple serait sign_a ^ = sign_b, sign_b = 0.C #
Je pense que la soustraction et la négation ne sont pas autorisées ... Quoi qu'il en soit:
la source
C avec SSE intrinsics (car tout va mieux avec SIMD):
Le gros avantage de cette implémentation est qu’elle peut être facilement adaptée pour effectuer 4 multiplications parallèles sans
*
ou+
si nécessaire.la source
la source
strlen(cg) != a
est une méthode très efficace pour éliminer le--
(le rend O (N * N)).Probablement trop vite :-(
la source
Cette version de Haskell ne fonctionne qu'avec des entiers non négatifs, mais elle multiplie de la manière dont les enfants l’apprennent pour la première fois. Par exemple, 3x4 est 3 groupes de 4 choses. Dans ce cas, les "choses" prises en compte sont des entailles ('|') sur un bâton.
la source
Cela peut fonctionner en C99, si le temps le permet, et si votre compilateur prend en charge les absurdités non définies.
la source
Puisque le PO n'a pas demandé le C , en voici un en SQL (Oracle)!
la source
*
s!Peut contenir des traces d'UD.
la source
Essai:
la source