Forum: Mikrocontroller und Digitale Elektronik Division 2 * 32 Bit mit 32 Bit


von Bit-Schieber (Gast)


Lesenswert?

Ich möchte zwei Zahlen miteinander multiplizieren. Mein Compiler 
unterstützt nur 32 Bit.

Um
1
1 048 575,5 * 0,5 = 524 278,75
zu berechnen, geh ich wie folgt vor:

Um den fraktionellen Teil darzustellen, verwende ich folgenden 
Faktor-Wert:
1
f: 1
2
o: 1 000 000 -> 0xF4240

Variablen:
1
signed integer a_fix  = 1 048 575 -> 0xf ffff
2
signed integer a_frac = 0,5 / 1 * 1 000 000 = 500 000 -> 0x7 a120
3
signed integer b_fix  = 0
4
signed integer b_frac = 0,5 / 1 * 1 000 000 = 500 000 -> 0x7 a120

Gewünschtes Layout des Ergebnisses:
1
[  f   i  x  ].[ frac ]
2
[32bit][32bit].[ 32bit]

Berechnung des Fix-Teils:
1
0xf ffff * 0x7 a120 => 0x7A 11f8 5ee0    // Ergebnis wird in 2 32 Bit Variable gespeichert
Berechnung des Frac-Teils:
1
0x7 a120 * 0x7 a120 = 0x3A 3529 4400    // Ergebnis wird in 2 32 Bit Variable gespeichert
2
3
0x7A 11f8 5ee0  ->  524 278 500 000 in Dezimal
4
5
524 278 500 000 / 1 000 000   = 524 278
6
524 278 500 000 mod 1 000 000 = 500 000      // fractional part
7
8
0x3A 3529 4400  ->  250 000 000 000 in Dezimal
9
250 000 000 000 / 1 000 000   = 250 000
10
250 000 000 000 mod 1 000 000 = 0

Result:
1
fix:  524 278 -> 
2
frac: 250 000 + 500 000 = 750 000 -> * 1 /1000 000 = 0,75
3
4
[  f   i  x  ].[ frac ]
5
[ 3 2  b i t][ 3 2  b i t].[ 3 2  b i t]
6
[          0][0x0007 FFFF].[0x000B 71B0]

Das Problem ist:
Fix-Teil des Ergebnisses ist als 2 * 32 Bit gespeichert. Den müsste ich 
jetzt dividieren, damit ich auf den korrekten Fix-Teil komme.
Da ist eben mein Problem. Ich sehe den Wald vor lauter Bäumen nicht... 
:(
Wie macht man Division "effizient" mit einem Wert, welcher in zwei 32Bit 
Variablen gespeichert ist!?
1
Sprich: 0x7A 11f8 5ee0 / 0xF4240 sowie 0x7A 11f8 5ee0 mod 0xF4240

von c-hater (Gast)


Lesenswert?

Bit-Schieber schrieb:

> Wie macht man Division "effizient" mit einem Wert, welcher in zwei 32Bit
> Variablen gespeichert ist!?

Indem man schon ganz zu Anfang möglichst sinnvolle Positionen für das 
Festkomma wählt. Nämlich so, dass sowohl die Aufbereitung der 
Eingangsgrößen als auch die Rückwandlung des Ergebnisses so wenig wie 
möglich Aufwand verursacht.

Je nach Hardware sollte also das Komma sowohl vor als auch nach der 
Operation an Byte-(oder Word- oder DWord-)Grenzen liegen, dann braucht 
man nur die Register "umsortieren", um an das Ergebnis zu kommen.

Manchmal geht das nicht, weil man halt vor oder nach dem Komma eine 
gewisse Mindeststellenzahl benötigt, dann ist das Schicksal und es kommt 
nur die zweitschnellste Lösung raus, die aber immerhin auch nur aus ein 
wenig zusätzlicher Bitschieberei besteht.

> [  f   i  x  ].[ frac ]
> [ 3 2  b i t][ 3 2  b i t].[ 3 2  b i t]

Wenn das dein gewünschtes Zielformat ist, dann wäre bei einer 
Multiplikation natürlich (in derselben Notation) folgendes Format für 
die Faktoren vorzusehen (im einfachsten Fall):

[  f   i  x  ].[ frac ]
[  3 2  b i t].[ 1 6  b i t]


Dann ergibt sich das Zielformat ganz automatisch richtig.

> [          0][0x0007 FFFF].[0x000B 71B0]

Du hast offensichtlich nicht mal die Fixkomma-Grundlagen begriffen. Der 
fraktionale Teil muss immer "linksbündig" im Register liegen, damit die 
Rechnererei funktionieren kann und auch im Ergebnis ist er dann 
linksbündig.

0.5 würde in einem 16-Bit-Register also 0x8000 bedeuten. Und im 
32Bit-Frac des Ergebnisses würden 0.75 sich dann als 0xc0000000 
manifestieren.

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.