Forum: Mikrocontroller und Digitale Elektronik 80 Bit / 80 Bit auf dem AVR dividieren


von Sven P. (Gast)


Lesenswert?

Huhu,

analog zu meinem vorhergehenden Problem: Wieder einmal eine 
Meinungssuche.
Ziel ists, eine 80-Bit-Festkommazahl (40.40) durch eine ebensolche Zahl 
zu dividieren, und zwar auf dem AVR.

Folgende Ideen habe ich:
- schnelle Schuldivision
- Newton-Verfahren (Nullstelle suchen, also quasi Newton-Raphson), dann 
mit dem Kehrwert multiplizieren
- Goldschmidt-Erweiterungsverfahren

Die Schuldivision wäre prinzipiell am einfachsten, allerdings komme ich 
mit den Registern in Bedrängnis: In 10 Registern rotiert der Rest, 10 
bräuchte ich für den Divisor und 10 für den Dividenten. Wobei für 
letzteren nochmals 10 weitere Register nötig sind, da ich ja vorher 
erweitern muss, damit die Nachkommastellen nicht verloren gehen.
Alternativ alles im SRAM vorhalten und mit Zeigern arbeiten, allerdings 
würde das die Laufzeit vervielfachen, was mir irgendwie misfällt.

Beim Newton-Verfahren müsste ich den Dividenten in den Bereich von 0.5 
und 1 bringen, letztlich also rechtsschieben. Dabei geht doch wieder 
jede Menge Genauigkeit verloren, oder?

Mit Goldschmidt habe ich mich zugegebenermaßen noch nicht weiter 
auseinandergesetzt. Das Prinzip kenne ich, nicht aber dessen Umsetzung 
auf 8-Bit-Hardware.

Was also tun?

Vielen Dank und Gruß,
Sven

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

> schnelle Schuldivision
Ich würde mal schauen ob du da nicht ggf. einztelne Teile der Rechnung 
Zeitweise in den RAM auslagern kannst (push/pop). (btw: gibt es auch 
eine langsame? ;)

> Newton-Verfahren
> Beim Newton-Verfahren müsste ich den Dividenten in den Bereich von 0.5
> und 1 bringen, letztlich also rechtsschieben. Dabei geht doch wieder
> jede Menge Genauigkeit verloren, oder?
mach halt ne 1.79 Zahl draus.

> mit dem Kehrwert multiplizieren
Wie bestimmst du den den Kehrwert? Wenn dir das einfach gelinngt dann 
nutzt das doch gleich un stat 80/80 rechnest du 80 * 1/80 ...

von Sven P. (Gast)


Lesenswert?

Läubi .. schrieb:
>> schnelle Schuldivision
> Ich würde mal schauen ob du da nicht ggf. einztelne Teile der Rechnung
> Zeitweise in den RAM auslagern kannst (push/pop). (btw: gibt es auch
> eine langsame? ;)
Welche denn? Ich brauche sie ja allesamt in jedem Durchlauf des 
Algorithmus'. Allein das Rotieren würde dann in ein endloses ldd+ror+std 
ausarten.


>> Newton-Verfahren
>> Beim Newton-Verfahren müsste ich den Dividenten in den Bereich von 0.5
>> und 1 bringen, letztlich also rechtsschieben. Dabei geht doch wieder
>> jede Menge Genauigkeit verloren, oder?
> mach halt ne 1.79 Zahl draus.
Wenn schon, dann eine 0.80-Zahl. Hm.

>> mit dem Kehrwert multiplizieren
> Wie bestimmst du den den Kehrwert? Wenn dir das einfach gelinngt dann
> nutzt das doch gleich un stat 80/80 rechnest du 80 * 1/80 ...
Das Newton-Verfahren dient der Bestimmung des Kehrwertes.

von Fragender (Gast)


Lesenswert?

Was willst du denn da eigentlich dividieren - die Anzahl der Atome in 
unserer Galaxis / Anzahl der Sonnensysteme im Universum?? ;-)

von Peter D. (peda)


Lesenswert?

Sven P. schrieb:
> Alternativ alles im SRAM vorhalten und mit Zeigern arbeiten, allerdings
> würde das die Laufzeit vervielfachen, was mir irgendwie misfällt.

Warum?
Hast Du überhaupt mal abgeschätzt, wie schnell Du die Division brauchst?

Es lohnt nicht, irgendwas zu optimieren, wenn es keinen merkbaren Effekt 
hat.


Peter

von Flo (Gast)


Lesenswert?

Sven P. schrieb:
> Ich brauche sie ja allesamt in jedem Durchlauf des
> Algorithmus'. Allein das Rotieren würde dann in ein endloses ldd+ror+std
> ausarten.

Jo, du setzt kurz deinen X-Zeiger, und dann ne schleife

ld r16, X
ror r16
st X+,r16

das ganze 10 mal, dauert doch nicht so lang.

von Sven P. (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Sven P. schrieb:
>> Alternativ alles im SRAM vorhalten und mit Zeigern arbeiten, allerdings
>> würde das die Laufzeit vervielfachen, was mir irgendwie misfällt.
>
> Warum?
> Hast Du überhaupt mal abgeschätzt, wie schnell Du die Division brauchst?
Ja schon, es ist mir auch bewusst, dass das immer noch schnell genug 
ist, das ist nicht das Problem. Die Sache ist damit schon schnell 
umgesetzt, allerdings interessierts mich halt, ob da nicht noch 
irgendwie eine anderer Ansatz exisitert. Rein aus Interesse an der 
Sache.

> Es lohnt nicht, irgendwas zu optimieren, wenn es keinen merkbaren Effekt
> hat.
Jo.

von Horst (Gast)


Lesenswert?

Sven P. schrieb:
> allerdings interessierts mich halt, ob da nicht noch
> irgendwie eine anderer Ansatz exisitert

Mein Ansatz:
1) Ich suche mir die ersten paar signifikanten Stellen, z.B. 16bit, dann 
bin ich im schlimsten Fall im zweiunddreißigstel Promille Bereich mit 
meiner Abweichung von ursprünglichen wert.
2) Dann nehme ich die normale Fließkommabibliothek meines Compilers.
3) Fertig.

Viel schneller wird's wohl nicht gehen. (Was die Umsetzung betrifft.)

Jetzt kommt sicher eine tolle Begründung, warum Du 80 signifikante 
Stellen brauchst? Oder soll das nur eine theoretische Übung sein?

von Sven P. (Gast)


Lesenswert?

Horst schrieb:
> Jetzt kommt sicher eine tolle Begründung, warum Du 80 signifikante
> Stellen brauchst? Oder soll das nur eine theoretische Übung sein?
Das soll eine Studie sein und ein kleiner Tischrechner werden. Ein 
bisschen rumeiern und Fließkomma und solala kann ich auch alleine, dafür 
hätte ich hier nicht nachgefragt.


PS: Das ist auch irgendwie typisch hier. Ich bin 22 Jahre alt, meines 
Erachtens weder ganz blöde noch minderbemittelt, also kurzum schon 
einigermaßen in der Lage, zu beurteilen, warum und wieso ich ein Problem 
habe und lösen möchte. Verzeihung.
Also ja, wenn es hilft, es soll eine 'theoretische Übung' sein.

von Fragender (Gast)


Lesenswert?

In diese Richtung ging auch meine Bemerkung weiter oben....
Ich kann mir einfach keinen vernünftigen Anwendungsfall vorstellen!

Die einzigen 80 Bit Zahlen, die ich kenne, sind Fließkommazahlen mit 
Mantisse und Exponent in den 80 Bit....

Aber als zahlentheoretische Programmierübung ist es natürlich 
möglich...ich persönlich würde da aber lieber was "Vernünftiges" 
programmieren.

Also nix für ungut!

von Sven P. (Gast)


Lesenswert?

Sehs doch mal anders: Das Festkommaformat ist 40.40, also jeweils 40 
Vor- und Nachkommastellen. Vorne steht noch die 
Zweierkomplement-Darstellung dran, also 39 Bit. Das ergibt dezimal einen 
Wertebereich von etwa +-549755813888, also etwa 11,5 Stellen.

Mein TI30 (Taschenrechner) rechnet insgesamt (Vor+Nachkomma) mit zehn 
Stellen, dafür aber mit einem laut Handbuch etwas unkonventionellen 
Fließkommaformat.

So weit weg sind die 80 Bit wirklich nicht. Zumal ich es ganz und 
garnicht leiden kann, wenn ich mit einem Rechner arbeite, der zwar 
irgendwelche Ergebnisse ausspuckt, ich aber hinten und vorne nicht weiß, 
wie falsch diese denn sind.
Bei dem 40.40-Festkommaformat hab ich einen klar definierten 
Wertebereich, in dem exakt gerechnet wird, fertig. Keine denormals, 
keine Lücken.

von Sven P. (Gast)


Angehängte Dateien:

Lesenswert?

Nach einiger Spielerei habe ich mal einen Dividierer zusammengeflickt 
(siehe Anhang).

Nach ersten Tests scheint der auch zu funktionieren, nur gefällt mir die 
Übergabe des Y-Zeigerregisters nicht so recht. Da arbeite ich momentan 
noch mit festen Adressen (push+pop nur, weil das Y-Register gleichzeitig 
für ein Arbeitsregister gebraucht wird); 'www' ist die Speicherstelle im 
SRAM, an der sich der Divisor befindet.
Da ich die Sache aber lieber schön gekapselt und komplett auf dem Stack 
hätte, misfällt mir eine feste Speicherstelle, um Y zwischenzuspeichern, 
auch :-/

von Maxx (Gast)


Lesenswert?

> Bei dem 40.40-Festkommaformat hab ich einen klar definierten
> Wertebereich, in dem exakt gerechnet wird, fertig. Keine denormals,
> keine Lücken.

Das erkaufst du dir jedoch mit anderen Problemen durch die enge 
Begrenzung des Wertebereichs. Für viele Rechnungen in schon kleinen 
Zehnerpotenzen völlig unbrauchbar.

Der VWLer kann nichtmal die Staatsschulden eintippen, geschweige denn 
damit rechnen.
Der Physiker stößt schon bei einfachsten Größenumrechnungen an die 
Grenzen. Lichtjahr in m z.B.
Der Chemiker kann nichtmal 'nen pH Wert ausrechnen. (10^14:1)

Davon abgesehen sind die "Lücken" im Grunde immer noch da, da hier der 
dominante Faktor nicht die absolute numerische Ungenauigkeit einer 
einzelnen Zahl ist, sondern der entstehende Fehler (der aus den 
absoluten Einzelfehlern multipliziert und addiert wird) wird durch die 
gesamte Berechnung bestimmt. (Vgl/Lese dazu "Kondition von 
(Berechnungs-)matrizen")

Für Taschenrechner bzw. andere Anwendungen, in denen der Wertebereich 
nicht eng definiert ist, ist Fixpunkt-Arithmetik keine sinnvolle Wahl 
imho.

von Sven P. (Gast)


Lesenswert?

Maxx schrieb:
>> Bei dem 40.40-Festkommaformat hab ich einen klar definierten
>> Wertebereich, in dem exakt gerechnet wird, fertig. Keine denormals,
>> keine Lücken.
>
> Das erkaufst du dir jedoch mit anderen Problemen durch die enge
> Begrenzung des Wertebereichs. Für viele Rechnungen in schon kleinen
> Zehnerpotenzen völlig unbrauchbar.
>
> Der VWLer kann nichtmal die Staatsschulden eintippen, geschweige denn
> damit rechnen.
> Der Physiker stößt schon bei einfachsten Größenumrechnungen an die
> Grenzen. Lichtjahr in m z.B.
> Der Chemiker kann nichtmal 'nen pH Wert ausrechnen. (10^14:1)
Dann sollte ich als Inschenör wohl die richtigen Einheiten wählen, hm?


> Davon abgesehen sind die "Lücken" im Grunde immer noch da, da hier der
> dominante Faktor nicht die absolute numerische Ungenauigkeit einer
> einzelnen Zahl ist, sondern der entstehende Fehler (der aus den
> absoluten Einzelfehlern multipliziert und addiert wird) wird durch die
> gesamte Berechnung bestimmt. (Vgl/Lese dazu "Kondition von
> (Berechnungs-)matrizen")
So meinte ich das nicht -- deine Ausführungen sind mir bewusst.
Im einfachsten Fall nehme ich meinen TI30 und rechne damit 
'ungeschickt': Der kann zwar bis x*10^99 rechnen, hat dabei aber immer 
noch nur 10 Stellen, nach meinen Versuchen im Falle des TI30 sogar nur 
10 zusammenliegende Stellen. D.h., nicht Gleitkomma, sondern eher Zahl 
plus Nullen. Die Rechnerei jenseits von meinethalben 10^30 erübrigt sich 
damit ohnehin, da stimmt bestenfalls noch die Größenordnung.

In diesem Versuch ist es mir lieber, ich weiß um den beschränkten 
Wertebereich meines Rechners. Selbst wenn ich damit einen pH-Wert 
berechnen möchte, dann lasse ich halt bewusst einige Stellen weg 
('teile') und merke mir den Fehler. Viel weiter komme ich mit meinem 
wissenschaftlichen Rechner auch nicht. Nur, dass der die Stellen still 
und mir u.U. unbewusst verschwinden lässt.

von Maxx (Gast)


Lesenswert?

Sven P. schrieb:
> Dann sollte ich als Inschenör wohl die richtigen Einheiten wählen, hm?

Wenn dir das immer möglich ist. Würd' immer ein System vorziehen, dass 
das Komma um entsprechende Einheiten verschieben kann.

> Der kann zwar bis x*10^99 rechnen, hat dabei aber immer
> noch nur 10 Stellen, nach meinen Versuchen im Falle des TI30 sogar nur
> 10 zusammenliegende Stellen. D.h., nicht Gleitkomma, sondern eher Zahl
> plus Nullen. Die Rechnerei jenseits von meinethalben 10^30 erübrigt sich
> damit ohnehin, da stimmt bestenfalls noch die Größenordnung.

Genau das ist Gleitkomma. Eine begrenzte Mantisse wird über einen Faktor 
mit Exponent auf Genauigkeit vs Wertebereich getrimmt.
Der relative Fehler bleibt dabei immer gleich und wird durch die Länge 
der Mantisse vorgegeben. (Bei dem TI30 dann irgendwo um die 10. 
signifikante Stelle)

> In diesem Versuch ist es mir lieber, ich weiß um den beschränkten
> Wertebereich meines Rechners. Selbst wenn ich damit einen pH-Wert
> berechnen möchte, dann lasse ich halt bewusst einige Stellen weg
> ('teile') und merke mir den Fehler.

Ich bezweifle, dass du das bei den nötigen Logarithmusberechnungen von 
Summen hinbekommst. Bei produkten okay.

Hier könnten (Hinzufügen von dissoziierenden Stoffmengen zu einer 
bestehenden wässrigen Lösung) z.B. Rechnungen wie
ld(2,1*10^13 + 7,8*10^11) auftreten. (Wobei du sicher noch keinen 
Logarithmus drin hast)

> Viel weiter komme ich mit meinem
> wissenschaftlichen Rechner auch nicht. Nur, dass der die Stellen still
> und mir u.U. unbewusst verschwinden lässt.

Och. Der kriegt die Rechnung oben locker hin.

von Ronny S. (Firma: Schmidt GmbH & Co.KG) (searay)


Lesenswert?

Man kann auch versuchen, einen Wald mit einer Nagelfeile abzuholzen - 
eine Lebensaufgabe. Übrigens: Ab Wieviel Bäumen kann man überhaupt von 
einem ´"Wald" sprechen - eine Frage für Philosophen - und natürlich für 
Juristen und Bürokraten (und damit eine sehr teuere)!!!!!!!!!!!!!!!!

von Sven P. (Gast)


Lesenswert?

Ich habe aber nicht um Belehrungen gebeten, warum das, was ich mache, 
schlecht ist, sondern ich habe eine m.M.n. recht konkrete Frage 
gestellt.

Auch das ist irgendwie wieder typisch für dieses Forum.
Wobei die ersten Antworten durchaus noch gute Denkansätze enthielten, 
auch über Sinn und Unsinn meines Problemes.

Aber dass ich unzurechnungsfähig und weltfremd bin, weiß ich selber, 
auch ohne Schmitt GmbH & Co.KG.

von Malte _. (malte) Benutzerseite


Lesenswert?

Motiviert durch diesen Thread habe ich einfach mal dc
http://en.wikipedia.org/wiki/Dc_(computer_program)
für einen AVR compiliert:
Beitrag "Just for fun: dc (an arbitrary precision calculator) port für AVR"
Geht (wenn man vom gelegentlichen Problemen mit vollem RAM absieht).

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Sven P. schrieb:
> Da ich die Sache aber lieber schön gekapselt und komplett auf dem Stack
> hätte, misfällt mir eine feste Speicherstelle, um Y zwischenzuspeichern,
> auch :-/
Du kannst es einfach "C-like" machen, und dir diesen Bereich auf dem 
Stack schaffen. (z.B. mit ADIW, per RCALL 0, per push...) leider fehlt 
in deinem Code wie groß der Bereich sein soll. Da du recht extensiv 
"mov'st": vielleicht ist dir an der ein oder anderen Stelle der movw 
Befehl hilfreich?

von Ralli (Gast)


Lesenswert?

Traurig, aber wahr:

Dieses Forum ist für fast ALLE µC-Fragen ALLERERSTE Wahl,
aber bei Mathematik-Implementation ist hier nicht viel zu holen!
Egal ob optimiert-genaue Problemlösung mit Integer-Mathematik oder
Festkomma.

Als Antwort gibts immer nur:
- Mach es doch mit der math.lib ...,
oder:
- Versteh nicht, warum willst du das überhaupt...

von Maxx (Gast)


Lesenswert?

Naja das WIE war behandelt.

Die offensichtlichen Konzeptfehler enthalten wir dir nicht vor, so 
gemein bin zumindest ich nicht. Musst ja nicht gegen die Wand laufen. 
"Warum" du das tust, also dennoch gegen die Wand läufst ist dann 
allerdings tatsächlich dir überlassen.

von Zapp (Gast)


Lesenswert?

Also ein Taschenrechner, resp das Tischmodell. Ja. dann gibt es gar 
keine Zeitlichen Anforderungen an die Zeit. Der der Benutzer ist immer 
langsamer.
Mach die Schuldivision, aber im RAM. Auch wenn das nun 10ms dauert... es 
koennten auch 100ms sein, und waere egal.

von Wolfgang M. (womai)


Lesenswert?

Was ist denn so schlimm daran wenn jemand 80-bit-Zahlen verarbeiten 
will? Ob das jetzt 48, 80 oder 8000 bit sind ist vom Konzept her ja 
ziemlich egal - wenn man schon seine eigenen Routinen schreibt, ist eine 
Aenderung der Laenge normalerweise trivial. Abgesehen davon gibt es 
durchaus praktische Anwendungen (z.B. Kryptographie), wo man so viele 
signifikante Stellen braucht.

@Sven P: Ich habe vor einiger Zeit einmal selber die Grundrechnungsarten 
fuer beliebig lange Integer-Zahlen implementiert (der Wechsel zwischen 
Integer un Festkomma ist trivial). Geschrieben fuer Microchip PIC, aber 
nachdem der Code in C ist, sollte ein Portierung auf AVR kaum oder keine 
Aenderungen brauchen. Die Zahlen sind binaer gespeichert, aber es gibt 
auch Routinen um sie als text zu drucken, oder Textstrings in 
Binaerformat zu konvertieren.

Link ist hier:

http://www.mikroe.com/forum/viewtopic.php?f=13&t=17654&p=90224&hilit=arbitrary#p90224

(aufpassen, der erste Post mit dem Code hat einen Fehler in der 
Addier-Routine - Korrektur findest Du weiter unten im Thread).

Wolfgang

von Joerg W. (joergwolfram)


Lesenswert?

Für meinen BASIC-Computer habe ich eine Fixkomma-Library geschrieben. 
Allerdings arbeitet die nicht binär, sondern in einer Art "Zwischending"
in dem ein Byte jeweils 2 Dezimalstellen repräsentiert. Aber eben nicht 
BCD sondern binär 0...99. Die Genauigkeit ist (fast) wie die von BCD 
Berechnungen, die Geschwindigkeit aber ein ganzes Stück höher.

Jörg

von Sven P. (Gast)


Lesenswert?

Uhh.

Wolfgang M.:
Daran werde ich mir ein Beispiel nehmen und die Chose mal unausgerollt 
(d.h. mit Schleifen) umsetzen.


Zapp:
Die meisten klassischen Tischrechner (HP z.B.) ließen sich 
programmieren. Unter Umständen fällt es dann schon ganz arg ins Gewicht, 
ob eine Routine 100ms länger braucht, oder nicht.
Nein, davon war bisher nicht die Rede, das weiß ich auch. Aber unnütz 
verschenken will ich erstmal nichts, das ist ja gerade der Spaß beim 
Programmieren in Assembler.


Läubi:
Ich werds mal in der Art versuchen: Mit adiw/sbiw den Platz besorgen und 
freigeben, dabei eines der Zeigerregister als Basiszeiger missbrauchen.


Joerg Wolfram:
Hättest du da Quellen für mich? Fände ich super :-)

Vielen Dank!

von Wolfgang M. (womai)


Lesenswert?

Joergs Loesung (jedes Byte entspricht zwei Stellen der Dezimalzahl) 
macht Konvertierung der Zahlen von/ins Textformat (z.B. zum Ausdrucken) 
natuerlich einfacher und auch schneller. Der Nachteil ist allerdings 
geringere Geschwindigkeit der Berechnungen selber (optimale 
Implementierung beider Varianten vorausgesetzt), weil eine gleich grosse 
Zahlen eben mehr Bytes benoetigt. Das faellt vor allem bei 
Multiplikation und Division ins Gewicht. Wenn also zwischen Eingabe und 
Ausgabe viele Rechenschritte liegen, wuerde ich meine Variante 
empfehlen. Wenn man - bei eine Taschenrechner durchaus moeglich - immer 
ein oder zwei Zahlen einliest, dann eine Rechenoperation ausfuehrt, und 
das Ergebnis wieder als Text ausgibt, ist Joergs Loesung potentiell 
schneller. Ehrlich gesagt habe ich seinerzeit auch zwischen diesen zwei 
Varianten geschwankt, mich dann aber fuer die rein binaere Loesung 
entschieden, weil ich das Endergebnis ohnehin binaer brauchte 
(48-bit-Tuningwort fuer einen DDS-Generator) und nie zurueckkonvertieren 
muss.

Wolfgang

von Wolfgang M. (womai)


Lesenswert?

Bei der Ausfuehrung auf dem PIC gibt es uebrigens Riesenunterschiede in 
der Geschwindigkeit zwischen 16F- und 18F-Serie - letztere hat einen 
Harware-Multiplizierer, das merkt man gewaltig (meine Routinen sind auf 
18F ca. 10x schneller bei Multiplikation und Division). Ob der Atmel 
einen Harware-Multiplizierer hat, weiss ich ehrlich gesagt nicht.

Wolfgang

von Rolf Magnus (Gast)


Lesenswert?

Wolfgang M. schrieb:
> Ob der Atmel einen Harware-Multiplizierer hat, weiss ich ehrlich gesagt
> nicht.

Die ATmegas haben einen, die ATtinys nicht.

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.