signed 18bit Integer richtig darstellen

Gast #7318563

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

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

@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

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 #7318626

Jens schrieb:

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.

Die Masken macht man sich zur Kompilezeit. Das Schieben zur Laufzeit. Nicht jeder µC hat einen Barrel-Shifter

Gast #7318673

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

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

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

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

Eine eigene Frage? Dieser Thread ist über 3 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.