Forum: PC-Programmierung Mehrwort-Multiplikation mit linearem Aufwand möglich?


von Joe K. (joker123)


Lesenswert?

Hallo Foren-Gemeinde,
wenn man eine Multiplikation durchführen möchte, aber durch die 
zugrundeliegende Maschine dahingehend eingeschränkt ist, dass die 
Maschine nicht den kompletten Wert auf einmal mit einem anderen Wert 
verrechnen kann, dann besteht ja der übliche Ansatz darin, dass man den 
Wert aufteilt und die Teile einzeln verrechnet.

Üblicherweise sind die Teile "1 Byte"-, "2 Byte"- oder "4 Byte"-groß. 
Ein "1 Byte"-großer Wert kann eine Zahl zwischen 0 und 255 sein. Man 
könnte daher ein Beispiel dahingehend vereinfachen, dass man einen Teil 
als einen Wert zwischen 0 und 9 ansieht und dann eine Dezimalzahl in 
seine Dezimalstellen auftrennt.

Beispiele:
1
12 * 34 = 408
entspricht in Einzelschritten (4 Multiplikationen + 3 Additionen):
1
   2 *  4 =   8
2
+  2 * 30 =  60
3
+ 10 *  4 =  40
4
+ 10 * 30 = 300
5
---------------
6
         == 408
1
123 * 456 = 56.088
entspricht in Einzelschritten (9 Multiplikationen + 8 Additionen):
1
    3 *   6 =     18
2
+   3 *  50 =    150
3
+   3 * 400 =  1.200
4
+  20 *   6 =    120
5
+  20 *  50 =  1.000
6
+  20 * 400 =  8.000
7
+ 100 *   6 =    600
8
+ 100 *  50 =  5.000
9
+ 100 * 400 = 40.000
10
--------------------
11
           == 56.088

1234 * 5678 führt nach dem selben Schema zu 16 Multiplikationen und 15 
Additionen.

Entsprechend ist der Aufwand, um eine Mehrwort-Multiplikation nach 
diesem Schema durchzuführen quadratisch von der Anzahl der 
Einzelteile/Wörter abhängig.

Nun möchte ich 2 Ganzzahlen miteinander multiplizieren, welche jeweils 
aus bis zu 64 Wörtern bestehen (bei der gegebenen Maschine). Es wären 
also nach dem bisherigen Schema 4.096 Multiplikationen und 4.095 
Additionen notwendig. Ich hoffe, dass nun das Problem definiert wurde.

Kann mir jemand einen Ansatz nennen, wie es möglich ist, dafür zu 
sorgen, dass der Aufwand zur Durchführung einer Mehrwort-Multiplikation 
reduziert wird?

Vielen Dank!

Gruß,
Joker.

: Bearbeitet durch User
von Heinz V. (heinz_v)


Lesenswert?

Z=A[n]*B

Label1:
ist LSB von A 1 dann:
   Addiere B zu Z
schiebe Z 1bit links
schiebe A 1bit rechts
solange A>0 jump Label1
hole nächstes A
Alle Multiplikatoren geholt?
wenn nein
  B:=Z
  jump Label1
ende

von ich (Gast)


Lesenswert?

Mit linearem Aufwand ist das nicht möglich, aber es geht besser als dein 
Quadratischer (n^2).
Noch einigermaßen verständlich und so ziemlich der schnellste 
Algorithmus (n^1,58...) wäre z.B. der Karazuba-Algorithmus
https://de.wikipedia.org/wiki/Karazuba-Algorithmus

Es gibt noch ein paar etwas schnellere (sind auch im Wiki verlinkt), die 
versteht man aber ohne Mathestudium eher nicht...

von Possetitjel (Gast)


Lesenswert?

Joe K. schrieb:

> Kann mir jemand einen Ansatz nennen, wie es möglich ist,
> dafür zu sorgen, dass der Aufwand zur Durchführung einer
> Mehrwort-Multiplikation reduziert wird?

Ja.

Wieder einmal helfen die Russen weiter: Das Zauberwort
heisst "Karazuba-Multiplikation".

Kernidee: Man kann (10*a+b)*(10*c+d) durch Ausmultiplzieren
und geschicktes Zusammenfassen so umformen, dass man mit DREI
(statt vier) Teilmultiplikationen auskommt. Diese Idee kann
man rekursiv auf die Teilprodukte anwenden.

Wikipädie liefert weiterführende Verweise, u.a. auf die
Toom-Cook- und zum Schönhage-Strassen-Algorithmen; die
Erklärung des Karazuba-Verfahrens finde ich dort allerdings
komplett unverständlich.

von Heinz V. (heinz_v)


Lesenswert?

Und als erstes prüfen ob einer der Faktoren 0 ist ;-)

von Joe K. (joker123)


Lesenswert?

Ich danke allen für die Antworten. Es braucht aber wohl ein bischen Zeit 
bis ich auf eurem Stand bin :-) Ich werde mal nach brauchbaren Quellen 
suchen, welche den Algorithmus dokumentiert haben.

Der Wikipedia-Artikel ist Müll, da er haufenweise unnötigen Balast 
enthält. Ich kann nicht mal eben ein Master-Studium in Mathematik 
nachholen nur um eine Multiplikation programmiertechnisch zu 
implementieren.

@Heinz V.: Ist der Pseudo-Code von dir eine Darstellung vom 
Karazuba-Algorithmus? Ich verstehe den Anfang nicht. Muss ich "Z" mit 
dem Wert "0" initialisieren? Ist "Z=A[n]*B" ein Kommentar über das was 
der Pseudocode tut? Oder muss ich "n" mit dem Wert "0" initialisieren 
und bei jedem "hole nächstes A" um 1 hochzählen?

: Bearbeitet durch User
von georg (Gast)


Lesenswert?

Possetitjel schrieb:
> dass man mit DREI
> (statt vier) Teilmultiplikationen auskommt

Ob das den Aufwand lohnt? Andrerseits gibt es fertige Libraries zum 
Rechnen mit beliebig grossen Ganzzahlen, da würde ich eine davon nehmen. 
Die sind wahrscheinlich eh schon so weit optimiert wie möglich, da kommt 
man mit einer Eigenentwicklung garnicht hin.

Georg

von Heinz V. (heinz_v)


Lesenswert?

Joe K. schrieb:
> @Heinz V.: Ist der Pseudo-Code von dir eine Darstellung vom
> Karazuba-Algorithmus?

Ich habe den Wikipedia Artikel nur kurz überflogem aber ich denke ja, 
gefunen hatte ih diese Methode in em Buch von Siemens 'Programmierung es 
SAB8080', ist aber schon eine Weile her, kann sein das ich mih mit der 
Richtung es Schiebens vertan habe.

> Ich verstehe den Anfang nicht. Muss ich "Z" mit
> dem Wert "0" initialisieren?

selbsverständlich

> Ist "Z=A[n]*B" ein Kommentar über das was
> der Pseudocode tut?

Ja

> Oder muss ich "n" mit dem Wert "0" initialisieren
> und bei jedem "hole nächstes A" um 1 hochzählen?

Ja

von Possetitjel (Gast)


Lesenswert?

georg schrieb:

> Possetitjel schrieb:
>> dass man mit DREI (statt vier) Teilmultiplikationen
>> auskommt
>
> Ob das den Aufwand lohnt?

Nun ja... bei vier Zerlegungsstufen ist Karazuba etwa
drei Mal schneller als das Standardverfahren. Lohnt sich
das?

von rbx (Gast)


Lesenswert?

Der Karazuba Algo wird von den Autoren Arno Eigenwillig und Kurt 
Mehlhorn vom Max-Planck-Institut für Informatik, Saarbrücken auf der 
Internetseite "Algorithmus der Woche" recht gut erklärt:

https://www-i1.informatik.rwth-aachen.de/~algorithmus/algo16.php

von Joe K. (joker123)


Lesenswert?

georg schrieb:
> Possetitjel schrieb:
>> dass man mit DREI
>> (statt vier) Teilmultiplikationen auskommt
>
> Ob das den Aufwand lohnt? Andrerseits gibt es fertige Libraries zum
> Rechnen mit beliebig grossen Ganzzahlen, da würde ich eine davon nehmen.
> Die sind wahrscheinlich eh schon so weit optimiert wie möglich, da kommt
> man mit einer Eigenentwicklung garnicht hin.
>
> Georg

In meinem Fall kann ich relativ viel Aufwand investieren, um den Ablauf 
zu optimieren, da ich damit beschäftigt bin eine solche Bibliothek zu 
schreiben. Es ist davon auszugehen, dass die Funktionen in verschiedenen 
Programmen zum Einsatz kommen. Wenn die Multiplikation nur bei einem 
einzelnen Programm zum Einsatz käme, hättest du wahrscheinlich recht.

Bei dem Pseudocode von Heinz V kommen außerdem Schiebebefehle zum 
Einsatz anstatt Multiplikationen. Dies ist insofern ein Vorteil, weil 
dann bei einigen Maschinen (zum Beispiel x86-Architektur) mit größeren 
Wörtern gearbeitet werden kann.

@rbx: Danke für den Link.

@Possetitjel: Meiner Erfahrung nach kommen aus Russland so einige 
nennenswerte Algorithmen. Auch im Bereich der Datenkompression gibt es 
einige begabte Russen.

@Heinz V: Danke für den Verweis auf die Quelle. Ich werde mal im 
Internet schauen, ob ich das Dokument finde. Vielleicht gibt es dort 
noch weitere ähnliche Tricks =)

Edit: @Heinz V: Dieses Buch? http://ontheserver.de/temp/Buch.jpg

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

> Bei dem Pseudocode von Heinz V kommen außerdem Schiebebefehle zum
> Einsatz anstatt Multiplikationen. Dies ist insofern ein Vorteil, weil
> dann bei einigen Maschinen (zum Beispiel x86-Architektur) mit größeren
> Wörtern gearbeitet werden kann.

Nicht wirklich. Das ist einfach deine Schulbuchmethode mit Binärzahlen. 
Wird häufig auf CPUs ohne Hardwaremultiplier als Softwarelösung 
eingesetzt.

von Heinz V. (heinz_v)


Lesenswert?

Joe K. schrieb:
> Edit: @Heinz V: Dieses Buch? http://ontheserver.de/temp/Buch.jpg

Exakt dieses.

foobar schrieb:
> Das ist einfach deine Schulbuchmethode mit Binärzahlen.

Ja, Du hast zwar recht, aber mit Binaerzahlen bedeutet die 
Multiplikation:

Multiplikator (1Bit) = 1 Multiplikant zum Proukt addieren
Multiplikator (1Bit) = 0 Springen ohne Addition

Bringt zumindest Geschwindigkeitsvorteile.

von foobar (Gast)


Lesenswert?

> Bringt zumindest Geschwindigkeitsvorteile.

Jo, ganz schöne Idioten, diese CPU-Designer: bauen mit viel Aufwand nen 
Hardwaremultiplier wo's doch mit Software viel schneller geht ...

... oder hast du evtl einfach nicht weit genug gedacht?

von Joe K. (joker123)


Lesenswert?

Ok, ich habe mir nun den Karazuba-Algorithmus angeschaut. Dank dem Link 
habe ich einigermaßen verstanden, wie er funktioniert. Es stimmt zwar, 
dass die Anzahl der Multiplikationen gesenkt wird, dafür wird diese 
Ersparnis durch zusätzliche Additionen und Subtraktionen wieder 
aufgefressen. Außerdem muss der Übertrag gehandhabt werden, was 
kostspielig ist.

Nach meinem Eindruck soweit ist der Algorithmus nur indirekt ein Gewinn, 
da eine Multiplikation bei der verwendeten Maschine ein Datenkopieren 
benötigt (die Werte müssen in bestimmten Registern sein, während bei 
einer Addition und auch bei einer Subtraktion die Werte in beliebigen 
Registern sein können).

Und so ein Algorithmus wird zum "Algorithmus der Woche"!? Naja, 
vielleicht habe ich bei der Ersparnis noch etwas nicht verstanden.

Der Pseudocode von Heinz V ist keine Implementation vom 
Karazuba-Algorithmus.

Edit: Ah, das ist eine Multiplikation auf Bit-Basis anstatt auf 
Wort-Basis. Danke für den Hinweis, foobar. Eine Schleife in einer 
Schleife. Die innere Schleife scheint durch "n" Bit für Bit vorwärts zu 
schreiten. Das Ergebnis scheint erst eine Ewigkeit später berechnet zu 
sein. :-/

Gibt es sonst noch Ansätze? Ich meine irgendwo gelesen zu haben, dass es 
tatsächlich einen linearen Ansatz gibt. Dies war auch mein Auslöser, 
dieses Thema überhaupt zu starten. Leider finde ich nichts hierzu. Es 
wäre echt schade, wenn ich dann im Endeffekt tatsächlich das 
implementieren muss, was viele kennen (Schulmethode) und nur wenige 
übertrifft.

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

> Ah, das ist eine Multiplikation auf Bit-Basis anstatt auf Wort-Basis.

Bingo! :-)

> Ich meine irgendwo gelesen zu haben, dass es tatsächlich einen linearen
> Ansatz gibt.

War wohl die Bild-Zeitung ;-) Man vermutet, dass die untere Grenze O(n * 
log n) ist - ne Algorithmus dafür hat man aber noch nicht gefunden.

> Wäre echt schade, wenn ich dann im Endeffekt tatsächlich das
> implementieren muss, was jeder kennt (Schulmethode) und niemanden
> übertrifft.

Bei deinen kleinen Zahlengrößen kann es gut sein, dass die Qualität der 
Implementation wichtiger ist als der Algorithmus an sich. Den Karazuba 
könnte man aber trotzdem mal ausprobieren - dann weiß man zumindest, ab 
welcher Größe die Implementation schneller wird :-)

von Karl (Gast)


Lesenswert?

Joe K. schrieb:
> In meinem Fall kann ich relativ viel Aufwand investieren, um den Ablauf
> zu optimieren, da ich damit beschäftigt bin eine solche Bibliothek zu
> schreiben. Es ist davon auszugehen, dass die Funktionen in verschiedenen
> Programmen zum Einsatz kommen. Wenn die Multiplikation nur bei einem
> einzelnen Programm zum Einsatz käme, hättest du wahrscheinlich recht.

Ist das eine akademische Übung? Dann gerne weiter.
Wenn es produktiv sein soll würde ich mich nochmal an die gmp setzen.

von Tippgeber (Gast)


Lesenswert?


von rbx (Gast)


Lesenswert?

Joe K. schrieb:
> Und so ein Algorithmus wird zum "Algorithmus der Woche"!? Naja,
> vielleicht habe ich bei der Ersparnis noch etwas nicht verstanden.

Die Ersparnis wirkt ein wenig wie beim Quadrieren mit Binomischer 
Formel:
z.B. 16*16 -> 160 + 60 + 6*6 bzw, 17*17 -> 170 + 70 + 7*7.. und das 
lässt sich ganz gut im Kopf rechnen.

(16*16 geht sowieso sehr schnell)

Es ist sehr zu empfehlen, den Algorithmus von Hand zu machen, bzw. zu 
vergleichen und Karazuba auch mit Hexadezimalzahlen probieren (um ein 
besseres Gefühl dafür zu bekommen, was bei der Implementierung gut geht, 
und was nicht - bzw. es kommt ein wenig auf die Hardware selber an.
(D.h. Beispielimplementation(en) anschauen.)

(Video gucken geht auch, aber es bringt nicht unbedingt viel, besser 
selber "antreten":
https://www.youtube.com/watch?v=E58q1dTZa68 )
("fünf Fragen..")

von max123 (Gast)


Lesenswert?

Eine Multiplikation ist nichts anderes als eine Faltung.
Die Signalverarbeiter kennen noch Begriff "Schnelle Faltung".

1.Die erste Zahl in ein Array schreiben.
(Z.B. aus 123 wird x[0,0,0,0,0,1,2,3]
Davon die  FFT bilden.

2.Die zweite Zahl wie die erste behandeln.

3. Array von der ersten Zahl mal Array von der zweiten Zahl
multiplizieren. (Faltung im Zeitbereich ist Multiplikation im
Frequenzbereich)

4.Davon InversFFT bilden.


Der Aufwand steigt mit n * ld(n).Habe vor vielen  Jahren diesen
Algorithmus mit LabVIEW erfolgreich getestet, aber nur im Wertebereich 
von
long * long. Soweit ich mich erinnere, habe ich die Idee aus dem Buch 
"Pi".

von A. F. (chefdesigner)


Lesenswert?

Ich bin doch recht erstaunt, dass es in der heutigen Zeit noch Maschinen 
gibt, die dererlei Verrenkungen nötig machen. Das kenne Ich wirklich nur 
von früher und der 8 Bit Zeit. Interessant, welche Lösungen es da gibt. 
Bei mir hat immer Herr Binomi zugeschlagen. Die Rechnungen waren 
entsprechend umfangreich :-)

von georg (Gast)


Lesenswert?

An F. schrieb:
> Ich bin doch recht erstaunt, dass es in der heutigen Zeit noch Maschinen
> gibt, die dererlei Verrenkungen nötig machen. Das kenne Ich wirklich nur
> von früher und der 8 Bit Zeit

Es ist doch völlig egal, ob eine CPU mit 4,8,16,32,64 oder noch mehr bit 
rechnet, wenn man längere Zahlen hat stösst man immer wieder auf das 
genau gleiche Problem.

Die derzeit grösste Primzahl hat 23 Mio Stellen. Ich glaube nicht, dass 
es in absehbarer Zeit eine CPU mit dieser Registerlänge gibt. Also doch 
weiterhin "verrenken".

Georg

von Joe K. (joker123)


Lesenswert?

Danke für die Rückmeldungen.

@foobar: Den Vergleich werde ich wohl machen, da ich mir noch nicht 
100%ig sicher bin, wie sich die Änderungen vom Karazuba-Algorithmus in 
der Praxis auswirken. Der Qualität von der Implementation wird ein 
angemessenes Gewicht zugewiesen. Der Ausführungsgeschwindigkeit jedoch 
auch. Zum Glück steht für die Bibliothek vergleichsweise viel 
Entwicklungszeit zur Verfügung.

@Tippgeber: Danke, die verlinkten Diskussionen bieten viel zum Lesen. 
Ich werde sie durchgehen, damit hier keine Wiederholungen notwendig 
sind. Ich hoffe allerdings, dass die Diskussionen tatsächlich wertvoll 
sind und nicht nur die ersten beiden Ergebnisse von einer automatischen 
Suche sind.

@rbx: Ja, einen Blick auf bereits bestehende Mathematik-Bibliotheken zu 
werfen, ist wohl ein guter Ansatz. Vielleicht kann ich hier oder dort 
von den Bemühungen von Vorgängern profitieren.

@chefdesigner: Es mag sein, dass du dies nun nicht sonderlich gerne 
liest. Du hättest gleich im ersten Beitrag lesen können, dass ich mit 
Ganzzahlen bestehend aus bis zu 64 Wörtern arbeite. Die Erinnerung an 
früher, als noch mit "8 Bit"-Maschinen gearbeitet wurde, obwohl die 
vorgegebene Wortbreite hier garkeine Rolle spielt, ist ein Beitrag von 
einer Art, welche schnell zur Offtopic-Diskussion führt.

@georg: Danke für die schnelle Erklärung für chefdesigner. Damit hast du 
vielleicht eine größere Offtopic-Diskussion abgefangen.

@Alle: Ich danke für die Materialien soweit. Ich bin dann erstmal wieder 
für eine Weile beschäftigt. :-)

von tictactoe (Gast)


Lesenswert?

Joe K. schrieb:
> Nun möchte ich 2 Ganzzahlen miteinander multiplizieren, welche jeweils
> aus bis zu 64 Wörtern bestehen (bei der gegebenen Maschine). Es wären
> also nach dem bisherigen Schema 4.096 Multiplikationen und 4.095
> Additionen notwendig. Ich hoffe, dass nun das Problem definiert wurde.
>
> Kann mir jemand einen Ansatz nennen, wie es möglich ist, dafür zu
> sorgen, dass der Aufwand zur Durchführung einer Mehrwort-Multiplikation
> reduziert wird?

Nur so am Rande: Wenn du weißt, dass dein Input maximal 64 Wörter hat, 
dann ist die Multiplikation IMMER O(1), egal welchen Algorithmus du 
verwendest. Wozu also suchen? ;)

von bestican (Gast)


Lesenswert?

> Ich meine irgendwo gelesen zu haben, dass es tatsächlich einen linearen
> Ansatz gibt.

War wohl die Bild-Zeitung ;-) Man vermutet, dass die untere Grenze O(n *
log n) ist - ne Algorithmus dafür ( 
https://www.deviceranking.de/phone/12978/xiaomi-mi-8-se ) hat man aber 
noch nicht gefunden.

> Wäre echt schade, wenn ich dann im Endeffekt tatsächlich das
> implementieren muss, was jeder kennt (Schulmethode) und niemanden
> übertrifft.

Bei deinen kleinen Zahlengrößen kann es gut sein, dass die Qualität der
Implementation wichtiger ist als der Algorithmus an sich. Den Karazuba
könnte man aber trotzdem mal ausprobieren - dann weiß man zumindest, ab
welcher Größe die Implementation schneller wird :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.