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
Quick&dirty:
1 | if (x & 0x20000) x = (x & 0x1ffff) | 0x10000000); |
:
Bearbeitet durch User
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
@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
Harry L. schrieb: > Quick&dirty: >
1 | > if (x & 0x20000) x = (x & 0x1ffff) | 0x10000000); |
2 | >
|
Das war natürlich ein Schnellschuss und Quatsch - sorry dafür! Wurde ja oben bereits korrekt gelöst.
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
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
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
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
> 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.
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; |
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?
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.