Forum: Mikrocontroller und Digitale Elektronik Integer-Zahl in binäre Festkommazahl wandeln


von Alexander I. (daedalus)


Lesenswert?

Hallo,

ich stehe gerade etwas auf dem Schlauch... ich hab hier ein digitales 
Filter in einem Controller, für den ich die Koeffizienten einstellen 
kann.

- Die Koeffizienten sind jeweils als "fractional signed values in two’s 
complement format" in einem 24 Bit breiten Register abgelegt.
- Der Wertebereich ist -1<=x<+1.

Mehr steht dazu erstmal nicht im Datenblatt.

D.h. beispielsweise das 0x7FFFFF ungefähr 1.0 entspricht und 0x3FFFFF = 
0.5 ist. Richtig?

Da die Filterfunktion in einem Treiber gekapselt sein soll, ist mit der 
Applikationsentwicklung vereinbart worden, dass diese die Koeffizienten 
als sint32 liefert und der Treiber für die Umrechnung in die binäre 
Festkommadarstellung zuständig ist:

Beispiele:
+1.0000 ist 1000000000,
+0.7450 ist 0745000000,
-0.0025 ist 0002500000
usw.

Gibt es jetzt eine komfortable Umrechnungsmöglichkeit in die binäre 
Festkommadarstellung oder hat jemand was, wo man sich ein wenig einlesen 
kann? Ich weiß nicht so recht, wonach ich bei Google suchen soll..

Vielen Dank vorab!

von Christian G. (christian_g83)


Lesenswert?

Alexander I. schrieb:

> +1.0000 ist 1000000000,
> +0.7450 ist 0745000000,
> -0.0025 ist 0002500000

Und was wäre +0.0025?

Christian

von Karl H. (kbuchegg)


Lesenswert?

Wenn bei euch
     +1.0000 ist 1000000000
gilt
und bei der Hardware
     +1.0000 ist 0x7FFFFF

dann würde ich doch mal sagen, das das ein simpler Dreisatz ist

   1000000000     ......   0x7FFFFF
     Wert         ......       x
   ---------------------------------

              Wert * 0x7FFFFF
      x = ---------------------
                1000000000


Aufpassen auf mögliche Overflows.



(Ich hab allerdings so ein Bauchgefühl, dass dir die Hex-Schreibweise 
Bauchweh bereitet. Zahl ist Zahl. Hex, Dezimal, Binär sind alles nur 
verschiedene Schreibweisen für ein und dasselbe: ein Bitmuster welches 
eine bestimmte Zahl repräsentiert)

von Karl H. (kbuchegg)


Lesenswert?

Alexander I. schrieb:

> Da die Filterfunktion in einem Treiber gekapselt sein soll, ist mit der
> Applikationsentwicklung vereinbart worden, dass diese die Koeffizienten
> als sint32 liefert

Schön und gut.
Da die APplikationsentwickler wahrscheinlich sowieso mit Fliesskomma 
rechnen, hättet ihr anstelle von

  > +1.0000 ist 1000000000,

einfach nur vereinbaren müssen, dass die Fliesskommazahl mit 8388607 (= 
0x7FFFFF) anstelle von 1000000000 multiplizert wird, und der Treiber 
müsste gar nichts tun.

Oder alternativ lässt du dir von den Applikationsleuten gleich den 
double geben und mutliplizierst das selber aus. Dann brauchen die sich 
keinen Kopf darüber zu zerbrechen.

von W.S. (Gast)


Lesenswert?

Alexander I. schrieb:
> - Die Koeffizienten sind jeweils als "fractional signed values in two’s
> complement format" in einem 24 Bit breiten Register abgelegt.
> - Der Wertebereich ist -1<=x<+1.
>
> Mehr steht dazu erstmal nicht im Datenblatt.

Das reicht ja auch völlig aus. Du hast es also mit echt gebrochenen 
Zahlen zu tun. Das MSB (offenbar Bit 23) enthält ne 1 für negative 
Zahlen und die folgenden Bits haben die Werte:

Bit 22: 0.5
Bit 21: 0.25
Bit 20: 0.125
usw.

Jetzt brauchst du ja bloß noch deine vermutlich auf irgendeinem Papier 
gedruckten Koeffizienten mit nem kleinen Progrämmelchen nach hex zu 
konvertieren und fertig.

Aber was ist sint32? signed long?
Sowas ist ungeeignet, weil integer und du hast es hier mit gebrochenen 
Zahlen zu tun.
Wenn schon, dann Gleitkomma.

W.S.

von eProfi (Gast)


Lesenswert?

Karl-Heinz, was muss ich da hören? 7FFFFF, welch ungerade Zahl!
Natürlich muss mit 0x00800000 multipliziert werden.

> D.h. beispielsweise das 0x7FFFFF ungefähr 1.0 entspricht
> und 0x3FFFFF = 0.5 ist. Richtig?
Nicht ganz, 0,5 ist 0x400000.

Als Programmierer muss man lernen, die dezimale Denkweise aufzugeben und 
binär zu denken. Habe ich hier schon mal erwähnt:
Beitrag "Re: Möglichst Resourcenschonend programmieren"
Beitrag "Re: Die genaue Sekunde / RTC"

von Alexander I. (daedalus)


Lesenswert?

Danke für die vielen Antworten...

- ein sint32 ist stdint.h-Schreibweise und ein signed integer mit 32 Bit 
Breite.
- Die Applschnittstelle ist fest definiert und der Übergabeparameter ist 
immer ein sint32. Da kann ich nicht einfach so nen double nehmen, wenn 
mir danach ist.

Ich denk die Beispiele von KHB und W.S. haben mir schon ganz gut 
weitergeholfen. Vielen Dank euch!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander I. schrieb:
> Gibt es jetzt eine komfortable Umrechnungsmöglichkeit in die binäre
> Festkommadarstellung
Du stocherst noch EXTREM im Trüben...
Eine Festkommazahl existiert NUR in deinen Gedanken! Die einfachste 
Umrechnung ist, dass du einfach eine vorzeichenbehaftete Integer-Zahl 
nimmst und (mental) durch einen bestimmten Faktor (am besten eine 2er 
Potenz) teilst. Dann bekommst du einige Bits vor dem Komma und einige 
nach dem Komma. Das lässt sich in Gedanken ganz problemlos soweit 
verschieben, dass du nur Vorkommastellen (integer) oder nur 
Nachkommastellen (-1...+0.99999, die +1 gibt es nicht!) hast. Der Trick 
an der Sache ist: der Prozessor merkt gar nichts davon, dass du in 
einer Festpunktzahl denkst. Er rechnet nur mit Integerzahlen!

> - Die Koeffizienten sind jeweils als "fractional signed values in two’s
> complement format" in einem 24 Bit breiten Register abgelegt.
Dann ist der Wertebereich also -2^23...+2^23-1 = -8388608 .... +8388607
> - Der Wertebereich ist -1<=x<+1.
D.h. du mußt nur diesen Wert in Gedanken durch 2^23 teilen:
-8388608/8388608 .... +8388607/8388608 = -1 ... +0.99999988079

> oder hat jemand was, wo man sich ein wenig einlesen kann?
Analog Devices haben Festkomma-DSPs. Dafür haben sie Handbücher, und 
dort ist das Zahlenformat sehr gut erklärt. Siehe dort
http://www.analog.com/en/processors-dsp/ADSP-21xx/processors/manuals/resources/index.html
>>> Using the ADSP-2100 Family Volume 1+2 <<<

W.S. schrieb:
> Das MSB (offenbar Bit 23) enthält ne 1 für negative Zahlen
> und die folgenden Bits haben die Werte:
> Bit 22: 0.5
> Bit 21: 0.25
> Bit 20: 0.125
> usw.
Dann wäre also +0.5 = 0x400000
und            -0.5 = 0xC00000   <-- das Bit 23 enthält eine 1   :-o
Richtig?
Falsch!

von Bernd (Gast)


Lesenswert?

Wäre es nicht eine Idee einfach 8 Bits nach links zu schieben und normal 
mit Single zu arbeiten?

von Karl H. (kbuchegg)


Lesenswert?

Alexander I. schrieb:

> - Die Applschnittstelle ist fest definiert und der Übergabeparameter ist
> immer ein sint32. Da kann ich nicht einfach so nen double nehmen, wenn
> mir danach ist.

Sagt auch keiner, dass du das mir nichts dir nix so ändern darfst.
Aber man kann mit den Leuten reden. Und wenn du die fragst, ob sie ihre 
Werte nicht eigentlich ohnehin schon als double im Bereich -1 bis +1 
haben und den jetzt extra wegen deiner API mit 1000000 multiplizieren 
müssen, nur damit du selber dann diese 1000000 dann wieder erneut 
umrechnest, dann kannst du ihnen anbieten, dass du mit einem double und 
einem Wertebereich von -1 bis +1 an der API viel glücklicher wärst und 
du ihnen damit eine Umrechnung ersparst.

Wenn die Applikationsentwickler ihrerseits gar nicht in double rechnen, 
sondern die ganze App mit Fixed Point Arithmetik aufgezogen haben, dann 
ist das sowieso hinfällig.

Woher kommt immer diese Attitüde, dass hausinterne API's in Stein 
gemeisselt sind. Die hat sich jemand ausgedacht, in dem er auch gewisse 
Annahmen einfliessen lies, wie die Dinge arbeiten. Wenn man drauf kommt, 
dass seine Annahmen nicht so glücklich waren, dann kann man mit diesen 
Menschen immer reden und ihnen zeigen, wie man mit Veränderungen das 
ganze noch vereinfachen kann. Die Leute beissen nicht. Das schlimmste 
was dir passieren kann ist, dass er Nein sagt.

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.