Ist es möglich, ein C-Programm zu schreiben, das zwei Zahlen multipliziert, ohne die Multiplikations- und Additionsoperatoren zu verwenden?
Ich habe dies bei Stack Overflow gefunden . Bitte helfen Sie diesem armen Programmierer bei seinem Problem. Und bitte geben Sie keine Antworten wie c = a/(1/((float)b))
, was genau das gleiche ist wie c = a*b
. (Und wird schon als Antwort gegeben.)
Die Antwort mit den meisten positiven Stimmen am 19. Januar 2014 gewinnt.
Hinweis: Dies ist eine Code-Trolling- Frage. Bitte nehmen Sie die Frage und / oder die Antworten nicht ernst. Weitere Informationen finden Sie unter Code-Trolling .
Antworten:
Verwenden Sie immer die Rekursion
Recusion ist der richtige Weg!
quelle
??::
ohne Klammern, eine für das Lösen des Problems, ohne zu versuchen, die Regeln zu ändern;)inc
Funktion testet ihr Argument, um festzustellen , ob das niedrigste Bit ist1
. Wenn dies der Fall ist, ruft er die verbleibenden oberen Bits des Arguments auf und gibt das Ergebnis mit demselben niedrigen Bit zurück, auf das der Haken gesetzt0
wurde. Wenn dies nicht der Fall ist (dh das niedrigste Bit ist0
), ersetzt er das0
mit einem1
und gibt das Ergebnis zurück . Der Vorgang ist sehr ähnlich zu dem, was Sie tun würden, wenn Sie die Werte von Hand addieren würden, Binärziffer für Binärziffer.Sie müssen das Programm jedes Mal kompilieren, aber es multipliziert alle positiven Ganzzahlen genau in jeder Version von C oder C ++.
quelle
"%zu"
Format - String.sizeof(char[A][B])
wird funktionieren (es sei denn, A <= 0 oder B <= 0 oder A * B überläuft. In diesem Fall sollte ein Fehler vom Typ 'bad type'main(){return sizeof(char[A][B]);}
und Sie kompilieren mitcc -DA=6 -DB=7 a.c; ./a.out; echo $?
Wenn Sie mit ein wenig Ungenauigkeit einverstanden sind, können Sie die Monte-Carlo-Methode anwenden :
Beispiel:
Ich denke das könnte gut genug sein;)
quelle
++
Operators sehen.-= -1
|= 1
(wird auf 50% der Zahlen arbeiten, 100% der Zeit)printf
Inkremente:printf("%*cc%n\n", count, &count, 'c');
(Druckt 'c', dann ein weiteres 'c' und speichert die Anzahl der zurückgeschriebenen Zeichencount
.Da Sie nicht angegeben haben, wie groß die Zahl ist, gehe ich davon aus, dass Sie zwei Ein-Bit-Zahlen meinen.
Wenn Sie eine maximal effiziente Implementierung wünschen, verwenden Sie die folgende winzige Implementierung:
Beachten Sie, dass immer noch nur Bits akzeptiert werden, obwohl die Typen implizite Ints sind. Sie benötigen weniger Code und sind daher effizienter. (Und ja, es wird kompiliert.)
quelle
return a && b;
. Es ist kürzer, also schneller.return a&b;
.#include<stdbool.h>
definierentrue
undfalse
.#include<stdbool.h>
scheint nur drei zu sein ,#define
s , die Sie selbst tun können (true
,false
,bool
und ein Flag zu markieren , dass es aktiviert ist schon). Sie können auch einen Trick aus einer der anderen Antworten nehmen und implizitint
für die "kurze" Version verwenden.Hier ist ein einfaches Shell-Skript, um dies zu tun:
UPDATE: Natürlich, um es in C zu tun, wickeln Sie es einfach in
exec("bash", "-c", ...)
. (Danke, AmeliaBR)quelle
%20
, um die Verwendung von+
Vorzeichen zu vermeiden .) Sie müssen jedoch die Ausgabe (in C) analysieren, um den Wert daraus zu erhalten. Das wird besonders schwierig, da die Ausgabe ein Bild und kein Text zu sein scheint. Durch HTML-Analyse und OCR ist dies möglicherweise die bestmögliche Antwort auf dieses Problem.Lassen Sie uns eine rekursive Halbierungssuche zwischen INT64_MIN und INT64_MAX durchführen!
PS Es wird glücklich mit einigen Werten sigsegv. ;)
quelle
Leider funktioniert dies nur für ganze Zahlen.
Da das Hinzufügen nicht zulässig ist, erstellen wir zunächst einen Inkrement-Operator:
Als nächstes müssen wir mit dem Schild umgehen. Finden Sie zuerst das Vorzeichenbit:
Dann nimm das Vorzeichen und die Stärke jedes Arguments. Um eine Zahl im Zweierkomplement zu negieren, müssen Sie alle Bits invertieren und eins hinzufügen.
Um zwei positive ganze Zahlen zu multiplizieren, können wir die geometrische Bedeutung der Multiplikation verwenden:
Trolle:
a++
wirklich als Hinzufügung? Ich wette, der Lehrer wollte es zulassen.<<
ist eigentlich die Multiplikation mit einer Zweierpotenz, daher sollte sie technisch nicht zugelassen werden.-1
ist nicht die beste Möglichkeit, das Vorzeichenbit zu finden. Selbst wenn keine eingebaute Konstante vorhanden wäre, könnten Sie eine logische Verschiebung nach rechts von -1 ausführen und dann alle Bits invertieren.MIN_INT
(AKAsignBit
) negativ ist, wird dieser Wert unterbrochen. Zum Glück klappt es immer noch in der Hälfte der Fälle, dennMIN_INT * [even number]
sollte Null sein.Außerdem werdenplusOne
Pausen-1
eingelegt, die zu Endlosschleifen führen, sobald das Ergebnis überläuft.plusOne
funktioniert gut für jeden Wert. Entschuldigung für die Verwirrung.quelle
(x ^ y) | ((x & y) << 1)
funktioniert nicht ganz, es wird kein Carry übertragen, wenn x oder y und Carry in derselben Position wahr sind :)Funktioniert auch für Gleitkommazahlen:
quelle
Jeder weiß, dass Python einfacher zu verwenden ist als C. Und Python verfügt über Funktionen, die jedem Operator entsprechen, für Fälle, in denen Sie den Operator nicht verwenden können. Welches ist genau unsere Problemdefinition, richtig? Damit:
quelle
Keine der anderen Antworten ist theoretisch zutreffend. Wie der allererste Kommentar zu dieser Frage besagt:
Wir müssen Multiplikation und Zahlen definieren, bevor überhaupt eine Antwort möglich ist. Sobald wir das tun, wird das Problem trivial.
Der beliebteste Weg, dies zu Beginn der mathematischen Logik zu tun, besteht darin , von Neumann-Ordnungszahlen auf der ZF-Mengen-Theorie aufzubauen und dann die Peano-Axiome zu verwenden .
Dies wird natürlich in C übersetzt, vorausgesetzt, Sie haben einen Settyp, der andere Sätze enthalten kann. Es muss nichts anderes als Mengen enthalten, was es trivial macht (nichts von dem, was
void*
in den meisten Mengenbibliotheken Unsinn macht ), also überlasse ich die Implementierung dem Leser als Übung.So zuerst:
Wenn Sie dies auf Ganzzahlen, Rationalitäten, Realzahlen, Surreals usw. erweitern möchten, können Sie - mit unendlicher Präzision (vorausgesetzt, Sie haben unendlichen Speicher und unendliche CPU) - booten. Aber wie Kroenecker berühmt sagte, machte Gott die natürlichen Zahlen; Alles andere ist das Werk des Menschen. Warum also die Mühe machen?
quelle
Wenn Sie den a [b] -Hack als Betrug ansehen (da es sich wirklich um ein Add handelt), funktioniert dies stattdessen. Bei Tabellensuchen werden jedoch auch Zeiger hinzugefügt.
Siehe http://en.wikipedia.org/wiki/IBM_1620 - ein Computer, der tatsächlich mithilfe von Nachschlagetabellen hinzugefügt hat ...
Etwas Befriedigendes daran, einen Tabellenmechanismus zu verwenden, um eine Operation zu beschleunigen, die tatsächlich in einer Anweisung ausgeführt werden könnte.
quelle
*
Saibling (obwohl es keine Multiplikation ist)Ich bin nicht sicher, was "Betrügen" in diesen "Code-Troll" -Postings bedeutet, aber dies multipliziert 2 beliebige Ganzzahlen zur Laufzeit mit no
*
oder+
operator unter Verwendung von Standardbibliotheken (C99).quelle
Meine Trolllösung für
unsigned int
:quelle
Hier gibt es viele gute Antworten, aber es sieht nicht so aus, als würden viele von ihnen die Tatsache ausnutzen, dass moderne Computer wirklich leistungsstark sind. In den meisten CPUs gibt es mehrere Prozessoreinheiten. Warum also nur eine? Wir können dies ausnutzen, um hervorragende Leistungsergebnisse zu erzielen.
Hier ist ein Beispiel für die Verwendung:
Die
#pragma omp parallel
Direktive veranlasst OpenMP, jeden Teil der for-Schleife auf eine andere Ausführungseinheit aufzuteilen, also multiplizieren wir parallel!Beachten Sie, dass Sie das
-fopenmp
Flag verwenden müssen, um den Compiler anzuweisen, OpenMP zu verwenden.Trollteile:
for
Schleife nicht wirklich - jeder Thread führt die Schleife aus.answer--
; Meistens wird es nicht angezeigt, aber gelegentlich werden ungenaue Ergebnisse erzielt.quelle
Leider ist die Multiplikation in der Informatik ein sehr schwieriges Problem. Die beste Lösung ist, stattdessen Division zu verwenden:
quelle
Im wirklichen Leben antworte ich normalerweise auf Trolling mit Wissen, daher hier eine Antwort, die überhaupt nicht trollt.
int
Soweit ich sehen kann, funktioniert es für alle Werte.Nach meinem besten Verständnis ist dies sehr ähnlich, wie eine CPU tatsächlich eine ganzzahlige Multiplikation durchführen könnte. Zuerst stellen wir sicher, dass mindestens eines der Argumente (
a
) positiv ist, indem wir das Vorzeichen auf beide setzen, wenna
es negativ ist (und nein, ich zähle Negation nicht als eine Art Addition oder Multiplikation). Dannwhile (a)
fügt die Schleifeb
dem Ergebnis für jedes gesetzte Bit in eine verschobene Kopie von hinzua
. Diedo
Schleife implementiert dier += x
Verwendung von und, xoder und das Verschieben einer Gruppe von Halbaddierern, wobei die Übertragsbits zurückgespeist werden,x
bis sie nicht mehr vorhanden sind (eine echte CPU würde Volladdierer verwenden, was effizienter ist, C jedoch nicht). Wir haben nicht die Operatoren, die wir dafür benötigen, es sei denn, Sie zählen den+
Operator).quelle
while(a)
Schleife niemals endet.quelle
while(C/A != B || C%A)
?Wirf dies in die Mischung:
Von der Infoseite .
- Etwas extrem Unannehmbares oder Unangemessenes in den Code einführen, das nicht entfernt werden kann, ohne alles wegzuwerfen, was die Antwort für das OP völlig unbrauchbar macht.
- […] Die Absicht ist, die Hausaufgaben in einer Sprache zu machen, die der faule OP für akzeptabel hält, ihn aber dennoch frustriert.
quelle
quelle
Sicher:
Aber das ist natürlich Betrug. Offensichtlich will er in der Lage sein, zwei Zahlen zu liefern, oder?
quelle
Es gibt keine Arithmetik wie die Zeigerarithmetik:
Die Funktion
f
implementiert die Multiplikation.main
nennt es einfach mit zwei Argumenten.Funktioniert auch für negative Zahlen.
quelle
a
, ja, negativb
denke ich nicht. Aber das kann auf viele kreative Arten behoben werden. Am einfachsten wäre sign_a ^ = sign_b, sign_b = 0.C #
Ich denke Subtraktion und Negation sind nicht erlaubt ... Egal:
quelle
C mit SSE-Eigenheiten (weil mit SIMD alles besser ist):
Der große Vorteil dieser Implementierung ist, dass sie leicht angepasst werden kann, um ohne
*
oder+
falls erforderlich 4 parallele Multiplikationen durchzuführen .quelle
quelle
strlen(cg) != a
ist eine sehr trollende Methode, um das zu eliminieren--
(macht es zu O (N * N)).Wahrscheinlich zu schnell :-(
quelle
Diese Haskell-Version funktioniert nur mit nichtnegativen ganzen Zahlen, aber sie multipliziert so, wie Kinder es zuerst lernen. Dh 3x4 ist 3 Gruppen von 4 Dingen. In diesem Fall sind die gezählten "Dinge" Kerben ('|') auf einem Stock.
quelle
Dies funktioniert möglicherweise in C99, wenn das Wetter stimmt und Ihr Compiler undefinierten Unsinn unterstützt.
quelle
Da das OP nicht nach C gefragt hat , ist hier eines in (Oracle) SQL!
quelle
*
s!Kann Spuren von UD enthalten.
quelle
Testlauf:
quelle