signed 18bit Integer richtig darstellen

Gast #7318563
Lesenswert?

Hallo zusammen,

ich bräuchte Hilfe. Ich habe ein IC, das 18bit signed Werte ausgibt. Jetzt will ich die Werte auf der Konsole mit printf() ausgeben. Das Problem ist nun, dass die negativen Werte nicht richtig dargestellt werden. Ich bekomme ständig Überläufe. Der Wertebereich liegt ja zwischen 131071 und -131072. Aber da ich die Zahlen auf int32_t casten muss (der µC kann ja keine 18bit Werte). Daher werden die Werte alle als positive Zahl behandelt.

Zwischen positiven und negativen Zahlen zu unterscheiden kann ich, wenn ich einfach das 17te Bit anschaue. Wenn das 1 ist, dann ist die Zahl negativ. Und jetzt kommt das Problem. Ich begreife nicht, wie ich nun die int32_t Zahl zusammenbauen muss, dass die Zahlen den richtigen Wertebereich zwischen 131071 und -131072 haben. Eigentlich müsste es doch reichen, wenn ich die Bits 19 bis 31 auf 1 setzt, wenn es eine negative Zahl ist und dann die 18bit Zahl einfach an die unteren Stellen kopiere. Aber irgendwie bekomme ich das nicht hin. Oder kann man das über eine normale Rechenoperation machen? Die Zeit spielt ja keine Rolle.

Ich wollte die Funktion so bauen, dass man die Bitbreite mit übergibt, so dass man auch 24bit Werte wandeln könnte (Das IC liefert auch solche - Ist ein Prototyp IC).

Der Compiler ist auf die erste Optimierungsstufe eingestellt und ich hab die Vermutung, dass da auch noch was reinfunkt.

Hat jemand von euch einen Gedankenanstoß für mich?

Danke euch!

Grüße, Jens

Gast #7318595
Lesenswert?

Hallo zusammen,

@Harry: Das funktioniert leider nicht. Muss man da nicht alle führenden Stellen auf eins setzen? nicht nur das Vorzeichenbit? Beim Überlauf auf die negative Zahl kommt da nicht das Richtige raus.

@Anja: Du hast Recht, es muss heißen: Bit 18 bis 31. Danke.

Grüße, Jens

Gast #7318597
Lesenswert?

@Andi: Das könnte gehen. Du meinst man macht die Zahl linksbündig. Dann erkennt der Compiler die negative Zahl und wenn ich die danach wieder nach rechts schiebe zieht er führende 1er rein. Das muss ich versuchen.

Oder meintest du das anders?

Grüße, Jens

Gast #7318617
Lesenswert?

Hallo zusammen,

die Lösung von Andi scheint super zu funktionieren. Das muss ich morgen nochmal intensiv testen. Diese Lösung finde ich sehr schön, da man durch das Schiften sehr leicht auf andere Wertebereiche ändern kann. Ich übergebe die Länge der Zahl im Funktionsaufruf. Dann ist es egal ob das 18bit oder 24bit oder was auch immer ist.

@Harry: Deine Lösung funktioniert vermutlich auch (ich hab es jetzt nicht getestet) aber die Bitmasken müsste man sich je nach Länge zusammenbasteln. Das ist dann mehr Aufwand als einfach nach links und rechts zu shiften.

Viele, vielen Dank an alle! Ihr habt mir echt geholfen!

Grüße, Jens

Gast #7318673
Lesenswert?

Anja schrieb:

Jens schrieb:

die Lösung von Andi scheint super zu funktionieren.

Aber nur solange Du den Compiler nicht wechselst. Rechtsschieben von signed Zahlen ist "implementation specific" in C.

Gruß Anja

Das stimmt zwar, aber normalerweise wird bei signed integer auch vorzeichenrichtig geschoben.

Wenn nicht: x << 14 >>> 14 oder: (x << 14) / 16384

Gast #7318765
Lesenswert?

Die Masken macht man sich zur Kompilezeit.

+++

Das Schieben zur Laufzeit. Nicht jeder µC hat einen Barrel-Shifter

Ein guter Compiler sollte erkennen, dass die Schieberei nicht noetig ist, und aequivalenten Code erzeugen.

Vermutlich wuerde ich es aber auch nicht darauf ankommen lassen.

Gast #7318774
Lesenswert?

Jens schrieb:

der µC kann ja keine 18bit Werte)

Doch. In einer Struktur als Bitfeld.

Dass Chip und uC beide 2er-Komplement haben, können wir nur vermuten.

Wenn Du schieben willst (statt direkt die Maske zu definieren), geht auch (mit n=Anzahl Bits)

1
#define M (0xFFFFFFFF<<n) //mask
2

3
   if(M&x) x|=M;
4

5
Oder alternativ:
6

7
#define m (1UL<<n) 
8

9
    If(x>=m/2) x-=m;
#7318779
Lesenswert?

Andi schrieb:

vorzeichenrichtig geschoben.

Du meinst, es wird ein "arithmetischer Shift" statt eines logischen ausgeführt.

Jens schrieb:

@Harry: Deine Lösung funktioniert vermutlich auch (ich hab es jetzt nicht getestet) aber die Bitmasken müsste man sich je nach Länge zusammenbasteln. Das ist dann mehr Aufwand als einfach nach links und rechts zu shiften.

Ändert sich die Anzahl an Bits, die dein IC ausgibt, denn ständig?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren