Forum: Mikrocontroller und Digitale Elektronik Multiplikatiom mit krummer Zahl


von Rockstein (Gast)


Lesenswert?

Hallo noch mal...

Jetzt sieht das Problem so aus. Es gibt ne riesige Zahl 32bit lang, die
muss ich mit einem koeffizient von 50/(2^32), also ungefaehr 0,011 mal
nehmen und das Ergebniss dann runden. Da im endeffekt eine kleinere
Zahl rauskommt, will ich die in 24 bits speichern.

Wie wird solche Multiplikation gemacht? Wie geht man voran.

<DANKE>

von thkais (Gast)


Lesenswert?

Das ist abhängig vom verwendeten Prozessor / Controller. Ich vermute, es
geht um Assembler?

von Joerg Wunsch (Gast)


Lesenswert?

Erstens könnte man einen Compiler befragen. ;-)

Zweitens ist natürlich eine 32-bit-Zahl geteilt durch 2^32 weiter
nichts als eine andere Betrachtung ebendieser 32-Bit Zahl.  Im
Wesentlichen ist das also eine Multiplikation mit 50.

Die größeren Probleme sind mögliche Wertebereichsüberläufe.  Wenn
der Wertebereich der Eingabezahl so klein ist, daß sie auch nach
einer Multiplikation mit 50 die 32 Bits noch nicht überschreitet,
ist das nicht weiter schwierig, ansonsten wird's aufwendig(er).

von Rockstein (Gast)


Lesenswert?

@thkais
Entschuldigung, habe vergessen zu sagen, dass es um einen AT90s2313
geht und natuerlich um Assembler, mit Bascom oder c ist das gar kein
Problem, leider wird sehr viel Speicher verbraucht.

@Joerg Wunsch
Ja, das ist mir klar, dass einiges der Compiler ausrechnen kann :-) wie
z.B. ldi R16, (2+3+4+5+6) aber das ist nicht der fall bei mir.
Ich habe mich oben verschrieben. Die Zahl sollte heissen
(50*10^6)/(2^32). Und wenn du sagst erst mal mit 50*10^6 mal nehmen,
dann bekomme ich auf jeden Fall ueberlaeufe bis hoechstens 64 bit. Aber
wenn mir jemand erklaert wie das geht, dann division durch 2^32 wird
durch wegnahme von 32 unteren Stellen gemacht. So stelle ich mir das
vor.

Also, falls jemand damit schon gearbeitet hat. Es handelt sich hier um
einen DDS chip von Analog Device AD9835. Da wird eine 32bit Zahl
reingeschrieben (nenen wie das mal asl Frequenzcode), die der Frequenz
am ausgang entspricht. Der Freq.code wird berechnet als
(Quarzfrequenz/2^32)*Frequenz. Die Aufgabe ist Frequenz zu aendern und
dabei auch anzeigen. Dabei wird der Code veraendert, dicht der
tatsaechlicher Frequenzwert. Und dann steht das Problem Code->Frequenz
Umwandlung

Kann mir jemand helfen?

von Joerg Wunsch (Gast)


Lesenswert?

Du wirst nicht um eine 64-Bit-Multiplikationsroutine umhin kommen
in diesem Falle.  Literatur zu solchen Algorithmen gibt's ja genug,
außerdem kannst Du in den Bibliotheken der freien C-Compiler Anleihe
nehmen.  Wenn Du wenigstens einen ATmega hättest (außer dem alten
103), dann wäre Dein Job einfacher, weil die zumindest 16 * 16 Bit
schon in Hardware können, die muß man dann ,,nur noch'' kaskadieren.

Die Division durch 2^32 bedeutet natürlich in der Tat, daß man die
unteren 32 Bit des Ergebnisses einfach ignoriert.

Irgendwann steht ein AD985x auch auf meiner Tagesordnung (liegt schon
ein Weilchen in der Schublade), aber ich würde solcherlei Krimskrams
dem Compiler überlassen und mich lieber der eigentlichen Arbeit
zuwenden. ;-)  Dafür würde ich mir aber ganz gewiß nicht von
vornherein Hände und Füße festzurren, indem ich mich auf einen
AT90S2313 festlege, zumal natürlich angesichts von Preis und
Stromaufnahme der DDS-Chips keinerlei Argument mehr dafür spricht,
ausgerechnet mit dem kleinsten AVR noch 64-Bit-Multiplikationen
anzuwerfen...  Ganz davon abgesehen, weniger Code als der Compiler
wirst Du für die Multiplikation ohnehin kaum bekommen.

von Rockstein (Gast)


Lesenswert?

Hm....
auf jeden Fall vielen Dank...Jetzt bin ich auch der Meinung, dass der
Compiler es besser machen kann. Ausserdem ueberlege ich mir die andere
Loesung ohne Mulriplikation. Der 2313 ist zu schwach dafuer denke ich
mal. Leider bin ich gezwungen einen 2313 zu nehmen, da es ein fertiges
Geraet ist, was ich nur modernisieren will indem ich dort eine
Frequenzanzeige einbaue.

von Peter D. (peda)


Lesenswert?

"Der 2313 ist zu schwach dafuer denke ich mal."

Aber nur, wenn Du statt des Quarzes höchstens 50Hz Taktfrequenz anlegst
oder einige Millionen Multiplikationen je Sekunde durchführen willst.


Ich weiß jetzt nicht, ob man heutzutage ausschließlich mit
Taschenrechnern Mathematik gelehrt bekommt.

Ich mußte in der Schule jedenfalls noch schriftlich rechnen lernen und
später kam dann auch noch das Rechnen in anderen Zahlensystemen  (z.B.
Binärsystem) dazu.
Beides kombiniert und schon weißt Du, wie man es mit jeder CPU machen
kann, nur mit Schieben und Addieren.

Ansonsten gibt es ja noch die 16Bit-Beispiele auf der Atmel-Seite.

Und der AVR hat ja auch 32 Register, damit kann man den Algorithmus
bequem mindestens auf 8Byte * 8Byte = 16Byte aufbohren, das sollte doch
wohl reichen.

Für den 8051 habe ich mal eine Arithmetikbibliothek geschrieben, die
mit Pointern arbeitet, d.h. die kann maximal mit 80Byte großen Zahlen
arbeiten.


Peter

von Rockstein (Gast)


Lesenswert?

@peter dannegger
Es gibt mir eine Hoffnung :)
Ok. Alle Operationen kann man nur mit Addieren (bzw subtr.) machen. Es
ist ja klar. Das problem ist die Geschwindigkeit. Wenn bei AVR so einen
Befehl gibt wie Multiplikation, was auch in einem Takt durchgefuert
wird, wieso soll ich  wie der alte Konrad Zuse alles durch Addition
machen. Ok... Ich gebe zu, dass im inneren des CPU es genau so per
Addition funktionier.

Ok. Ich versuche jetzt gerade mir klar zu machen wie die Rechnung in
Binaersystem funkzioniert. Es ist nicht schwirig. Wenn ich was fertig
kriege bzw. nicht kriege schreib ich hier.

Und noch ne Frage. es gibt eine Behauptung, dass der Compiler das
genauso machen wuerde wie ich, wenn ich selbst mir eine Assembler
subroutine schreibe. Ist das so oder macht der Compiler den groeseren
Code???

von thkais (Gast)


Lesenswert?

Die Binäre Multiplikation ist überhaupt nicht wild. Wenn Du in der
Schule die Multiplikation von Hand gelernt hast - geht genauso. Als
Beispiel eine 4 x 4 Bit Multiplikation:
Man muß nur die "1001" bei jedem Schritt um 1 nach links shiften, und
entweder addieren oder eben nicht. Eine 32 x 32 Bit-Multiplikation läßt
sich in 32 Schritten erledigen, das klappt auch mit dem 2313.

      1001 x 1101
-------------------
      1001   1
     0000    0
    1001     1
   1001      1
-----1-------------
   1110101

Der Compiler macht i.a. einen größeren Code, weil er nicht speziell
angepaßten Code erzeugt, sondern auch Sonderfälle (negative Zahlen,
Überträge, Fehlermeldungen bei Überlauf) berücksichtigen muß, während
"von Hand" assembliert einige Sonderfälle von vornherein
ausgeschlossen werden können. Allerdings sollen die Atmel-Compiler
(sowohl C als auch Basic) ein recht geringes Overhead haben.

von Rockstein (Gast)


Lesenswert?

@thkais

Stimmt, das verstehe ich. Und die ganze Multiplication ist ja nur AND
operation :)
Also, so werde ich vorgehen.

Dann hat der Joerg Wunsch nur teilweise recht :)
...von seinem posting
<b> Ganz davon abgesehen, weniger Code als der Compiler
wirst Du für die Multiplikation ohnehin kaum bekommen. </b>

Folgendes ist mir eingefallen. Wenn ich ne Frequenz z.B.
14000000(14Mhz) binaer darstellen will, dann brauche ich nur 24bit. In
Bascom bzw. C kann man nur zwischen 16 und 32bit waehlen. Man sieht das
glaube ich deutlich, wenn ich 10 variablen von 24bit brauche, dann
verschwende ich min Bascom 10 byte... Ist ja nicht gut

von Rockstein (Gast)


Lesenswert?


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.