Forum: Digitale Signalverarbeitung / DSP / Machine Learning Hilfe zu fractional oder festkomma arithmetic


von Florian (Gast)


Lesenswert?

Hallo,

ich habe grade einen grossen hänger.
ich möchte z.b diese Zahlen multiplizieren

4095 * 2.1 = ?
mit Fließkommamultiplikation dauert das so um die 350 Zyklen. das ist zu 
lang. Möchte das ganze mit fractional lösen. So laut diverser Quellen
liegt der Zahlenbereich von fractional von 1 bis -1. Soweit ok. nehme 
meine
4095 teile sie durch 32768 und hab die entsprechende fractionalzahl.
wie kann ich die jetzt mit 2.1 multiplizieren ? Mein mC kann entwerder 
fractional- oder integermode, ( wobei 2.1 kein integer ist ) ich habe 
mir selber 2 Ansätze überlegt. entweder mach ich aus dem 1.15 format zb 
ein 4.12 format oder ich teile die 2.1 auch durch 32768 und 
multipliziere das ergebnis mit 32768². Bei der zweiten Methode werden 
werden aber meine Register zu kurz sein, denn ich muss ja eine 16bit 
zahl mit einer 32 bit Zahl multiplizieren ka ob das geht.
Wie gesagt mein Problem ist, dass alle Quellen die ich zu diesem Thema 
gelesen habe von einem 1.15 format ausgehen. Auch habe ich diverse 
beispielcodes für PID Regler oder FIR_Filter die ebenfals von einem 1.15 
Format ausgehen. grade beim PID Regler muss aber eine Zahl mit einer 
anderen Zahl  grösser 1 multiplizieren können .

Es kann sein das ich fractional total falsch verstanden hab.
Habe ich warscheinlich auch. Es ist doch so das bei einem 1.15 Format
also eine Stelle vor dem Komma und 15 stellen nach dem Komma (bzw das
Bit vor dem Komma ist das Vorzeichenbit) die Stellenwertigkeit = 2¯¹
,2¯²,2¯³...... ist ?

naja,Ich hoffe das man Problem verstehen kann und das ich hier hilfe 
bekomme.

von Alban (Gast)


Lesenswert?

> 4095 teile sie durch 32768 und hab die entsprechende fractionalzahl.
> wie kann ich die jetzt mit 2.1 multiplizieren ?

Ich würde lieber die 2.1 in eine fixed point Zahl umwandeln und dann mit 
4095 multiplizieren.

Jetzt ist halt die Frage wie genau du das brauchst. Die 0.1 lassen sich 
nicht so genau darstellen und um so genauer du es brauchst, um so mehr 
Bits must du spendieren.

Also mal angenommen anstatt 0.1 währe 0.125 möglich -> 1/8. Dann 
könntest du 2.125 mit U(2,3) darstellen. U steht für unsigned, 2 integer 
Bits und 3 fraktionale Bits.

Um 2.125 in das Format umzuwandeln, must du die Zahl mit 2^3 
multiplizieren. -- Das ist die Anzahl an fraktionalen Bits --.

2.125 * 2^3 = 17

Um das mal zu verdeutlichen 17 -> b10.001
Die Wertigkeit ist 2^1 2^0 . 2^-1 2^-2 2^-3

Die 17 kannst du jetzt mit 4095 multiplizieren, musst aber noch eine 
Berechnung durchführen, was dein Ergebnis dann nacher bedeutet. 4095 
kann mit 12 Bit unsigned dargestellt werden, in fixed point Notation 
U(12,0).

Die fixed point Regel besagt jetzt für unsigned Multiplikation:

U(a1,b1) * U(a2,b2) = U(a1+a2,b1+b2)

Also U(12,0) * U(2,3) = U(14,3)

Zur Berechnung: 4095 * 17 = 69615

Wenn du jetzt wissen willst was das Ergebnis für einen floating point 
Wert darstellt, teile das Ergebnis einfach durch 2^3.

69615 / 2^3 = 8701,875

Das ist auch genau was 4095 * 2.125 ergibt.

von vorgon (Gast)


Lesenswert?

Hi vielen Dank für dein Post,
hat mir super weitergeholfen.

von DSPNeuling (Gast)


Lesenswert?

Hallo,


das angegebene Beispiel kann ich auf mein Problem nicht anwenden. Ich 
habe einige Quellen dazugelesen und ich verstehe das immer noch nicht. 
Ist das so schwer oder übersehe ich etwas. Ich fand folgende Quellen 
informativ:

http://www.acoustics.hut.fi/teaching/S-89.3510/2006/projektityo/FixedPointDSPDev.pdf
http://www.digitalsignallabs.com/fp.pdf

Diese haben mich nicht weitergebracht. Was ich machen will, ist, 
FIR-Filter, die kleiner +1 und größer sind -1 in fixed-point darstellen 
und multiplzieren.

Z.B. coef=-0.2345, sample=4095

res=-0.2345*4095=-960.2775

danach kommt eine Addition des vorherigen Wertes.


Kann mir da jemand weiterhelfen?


Danke!

von Detlef _. (detlef_a)


Lesenswert?

>>Z.B. coef=-0.2345, sample=4095
>>res=-0.2345*4095=-960.2775

Du skalierst Deinen Coeffizienten: -0.2345 = -61473/2^18

Also 4095*-61473 rechnen und dann durch 2^18teilen, indem man das 
Ergebnis 18 Stellen nach rechts schiebt, Ergebnis ist -960. Die 
verfügbare Bitzahl bestimmt die Genauigkeit: 4095 sind 12Bit, 61xxx sind 
16Bit, multipliziert gibt das 28, 1 fürs Vorzeichen und bißchen Reserve.

Für nen ganz groben Hack könnte man die 4095 auch einfach 2 Bit 
rechtsschieben, dann hieße der Coeffizient 0.25.

Gute Nacht
Detlef

von DSPNeuling (Gast)


Lesenswert?

Hi,

danke für die Antwort. Ich habe da noch ne Frage. Was mache ich, wenn 
ich nur 16-bit für das Ergebnis zur Verfügung habe. Kann ich nicht das 
Ergebnis in 16-Bit mit Bitverschiebung darstellen?

Was ich machen will, ist, zwei short (16-bit) Variablen zu 
multiplizieren. Das Ergebnis soll dann auch short sein.

Noch was zur Theorie: Ich habe gelesen, dass bei der Integer-Multip. von 
ANSI Standard (16x16=32) die untere Hälfte des Ergebnisses aus der 
Multipl. erhalten bleibt, während in der Fixed-Point-Arithmetik die 
obere Hälfte erhalten bleibt.

Kann mir das jmd erklären, wie ich an die obere Hälfte rankomme? Mit 
Zahlenbeispiel bitte.


Danke nochmal!

von Detlef _. (detlef_a)


Lesenswert?

DSPNeuling wrote:

> Was ich machen will, ist, zwei short (16-bit) Variablen zu
> multiplizieren. Das Ergebnis soll dann auch short sein.
>

Das Ergebnis ist 16 Bit lang. Eine 16Bit Zahl mit einem Koeffizienten 
betragsmäßig kleiner 1 multipliziert ergibt wieder 16 Bit Ergebnisse. 
Das Zwischenergebnis vorm schiben ist länger, 16Bit*16Bit =32 Bit.

>Ich habe gelesen, dass bei der Integer-Multip. von
> ANSI Standard (16x16=32) die untere Hälfte des Ergebnisses aus der
> Multipl. erhalten bleibt, während in der Fixed-Point-Arithmetik die
> obere Hälfte erhalten bleibt.

Die Frage verstehe ich nicht.

> Noch was zur Theorie:

'Grau ist alle Theorie und grün des Lebens goldner Baum'

Cheers
Detlef

von DSPNeuling (Gast)


Lesenswert?

Hi Detlef,



<Das Ergebnis ist 16 Bit lang. Eine 16Bit Zahl mit einem Koeffizienten
<betragsmäßig kleiner 1 multipliziert ergibt wieder 16 Bit Ergebnisse.
<Das Zwischenergebnis vorm schiben ist länger, 16Bit*16Bit =32 Bit.


(4095*-61473)/2^18 = -960 Steht das Ergebnis in MSB oder LSB? Das ist 
oben meine Frage gewesen? Wird MSB oder LSB ausgegeben?

Ergebnis ist 28 bit, hattest du geschrieben. Wie kann ich das jetzt auf 
16 Bit reduzieren?

Und warum skalierst du mit 18 und nicht mit 15? Wenn ich nur 15 bits zur 
Verfügung habe?


Irgendwie verstehe ich das immer noch nicht :-( Ich will das verstehen.

von detlef _a (Gast)


Lesenswert?

Rechnung mal genau, allerdings ohne negatives Vorzeichen:

4095*61473=251731935
Jetzt im hexadezimalen Zahlensystem (0x ist der Präfix für hex-Zahlen)
0xfff*0xf021=0xf011fdf

LSB/MSB kann least/most significant Bit oder Byte heißen, das spielt 
aber keine Rolle. Nach der Mutiplikation hat das Ergebnis 0xf011fdf 28 
Bit. Die oberen 12Bit (das HighWORD) ist 0xf01, das lowword 0x1fdf ist 
16Bit lang. Die 28 Bit passen in ein 32 Bit Wort rein.

Jetzt kommt das Teilen durch 2^18. Teilen durch 2 macht man durch 
Schieben des 32 Bit Wortes um eine Stelle nach rechts:
0xf011fdf >>1 = 0x7808fef
Das Ergebnis hat nur noch 27Bit. Das insgesamt 18Mal machen (/2^18) läßt 
10Bit übrig, die passen wieder in ein 16Bit Wort. Für das Ergebnis der 
Multiplikation braucht man aber die 32Bit.

>>nd warum skalierst du mit 18 und nicht mit 15?

32Bit brauch ich sowieso, wenn ich mit 15 skaliere statt mit 18 
verschenke ich ohne Not Genauigkeit.

>>Ergebnis ist 28 bit, hattest du geschrieben. Wie kann ich das jetzt auf
>>16 Bit reduzieren?

Schieben, 18 Mal nach rechts.

>>Ich will das verstehen.
Finde ich gut !

Cheers
Detlef

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.