Hallo,
ich bekomme von einer etwas umständlichen Dekodierung einen binären String zurrück, der 28 Bits enthält. Er repräsentiert eine zweierkomplement Zahl, die also auch negativ werden kann. Ich verzweifel nun etwas an der konvertierung dieses Strings, da ich einfach keine negativen Werte erhalte.
Ich hab dazu mal die Funktion strtol() getestet. Mit einem String, der einem Integer-Wert entspricht, klappt das. Bei der Ausgeabe in eine Long-Variable aber nicht. Was mache ich falsch?
Hier mal der Test-Code. Das Ganze findet auf einem Mega mit ATmel1280 statt, daher ist der Int 16Bit lang.
Den String hab ich mal auf 32 Bits verlängert (statt der 28Bits von der Dekodierung), damit das überhaupt klappt.
Das höchste Bit wird als Vorzeichen interpretiert. Bei long wäre das das 31. Bit, bei 28 aber das 27. Bit. Man kann dann entweder das bekannte Vorzeichen-Bit in die unbelegten Bits bis 31 kopieren, oder die Zahl vor der Konvertierung um die fehlenden 4 Bits nach links schieben.
@michael: Der String hatte 32 Bit (siehe Deklaration). Warum der in der Ausgabe nun auf 31 gekürzt wird, ist ein weiteres Rätsel für mich. In der Konvertierung von Srting zu char Array hänge ich immer ein char extra dran für den Termination Character, daher müsste eigentlich in dem Code 32 Bits als Ausgabe rauskommen...
Ich weiß leider nicht, wie ich die Ausgabe mit dem Bit-String ändern soll. Das übersteigt meine Fähigkeiten wohl...
@michael: Das gibt mir den Wert aber auch nicht als Zweierkomplement raus.
Merkwürdig, dass die Funktion, die extra für Long Zahlen ist, genau hier nicht funktioniert. Bei Integern klappts damit ja.
Man müsste ja eigentlich auch einfach den Wert regulär umwandeln können, also ohne Vorzeichen, ihn dann invertieren und +1. Klappt aber auch nicht. Wenn ich den Wert invertiere, wird einfach nur das Vorzeichen geändert.
Habt Ihr noch eine andere Idee, wie das klappen könnte? Den binären String zerlegen oder so?
Mir fällt auch gerade auf, dass die von strtol ausgegebene Zahl dem maximalen Wert eines Long Wertes entspricht.
leclerke:
Habt Ihr noch eine andere Idee, wie das klappen könnte? Den binären String zerlegen oder so?
Mir fällt auch gerade auf, dass die von strtol ausgegebene Zahl dem maximalen Wert eines Long Wertes entspricht.
#include <Streaming.h>
void setup()
{
Serial.begin(9600);
Serial << "Start: "<< __FILE__ << endl;
char text[] ="1111111111111111111111111110"; // 28 Bit signed -2
Serial << "strlen: "<< strlen(text) << endl;
long a = strtol(text,nullptr,2);// wandlung zu long
a|=1ul<<27&a?0b1111ul<<28:0; // vorzeichen auf 32Bit erweitern
Serial << "a: "<< a << endl; // zeigt -2
}
void loop()
{
}
EDIT:
Code geändert.
Jetzt mit Vorzeichen Erweiterung für die 28Bit zu 32Bit Konvertierung.
leclerke:
Ähm, wie kann dass denn klappen? Also es klappt, aber warum ausgerechnet mit der string to UNSIGNED long?
Weil beide Funktionen dummerweise kein Zweierkomplement lesen können!
strtol() erwartet bei negativen Zahlen ein Vorzeichen!
Serial << "v: "<< strtol("-10",nullptr,2) << endl; // zeigt -2
Mit strtoul() bekommt man die 32 Bit überhaupt erst unverfälscht in den Speicher.
Der cast nach long übernimmt dann das umtaufen auf Vorzeichen behaftet
Aber wie schon gesagt, mit der "neuen" Variante ist alles besser.
Die 28 Bit machen auch bei strtol() keine Probleme,
Nur das Vorzeichen muss angepasst/repariert werden.