Hallo,
ich hab eine Denkblockade.
folgendes Problem
ich kriege die Sekunden von einer App als Hex Wert gesendet.
Beispiel: 54 sec
wird gesendet als int mit Wert 84[Dec] was einer 54[Hex] entspricht.
Wie kriege ich jetzt die 54[Hex] in eine 54[Dec] gewandelt?
Meine Idee wäre es die 84 als Hexadezimalen string zu printen und dann
den String in ein Int umwandeln.
Gibts da was schöneres?
Schau mal ob das dein Problem lösen kann:
https://cplusplus.com/reference/cstdlib/strtol/
1. Parameter: Input: Pointer auf den HexString.
2. Parameter: Output: Hier wird ein Pointer auf das erstes Zeichen nach
der geparsten Zahl zurück gegeben, einfach 0 übergeben, wenn du es nicht
brauchst.
3. Parameter: Input: Die Bases der Zahl, bei Hex ist es 16
Lothar M. schrieb im Beitrag #7305249:
>> Wie kriege ich jetzt die 54[Hex] in eine 54[Dec] gewandelt?> Eine Wandlung ist evtl. gar nicht nötig, denn das ist beide Males die> selbe Bitfolge: "0101_0100". Nur jeweils anders dargestellt.
Ich denke Lothar hat recht. Du bekommt ein gepacktes BCD Format. 4 Bit
für die Zehnerstelle und 4 Bit für die Einer Stelle.
Nur dein Programm oder das Programm mit dem du dir das anschaust
erwartet eine normale 8 Bit binärzahl und zeigt die entsprechend an.
Beispiel:
24 Sekunden werden als 0010 0100 (2 4) ausgegeben. Für dein Programm ist
das aber eine 00100100, also eine 36.
John P. schrieb:> wird gesendet als int mit Wert 84[Dec] was einer 54[Hex] entspricht.
Da kommt wirklich der Dezimalwert des Hex-Wert in einem int? Wer macht
denn sowas?
Wenns wirklich so ist, rechne halt zu Fuß um: abs(84/16) *10 + Rest *16
Werte über 9 (die Buchstaben benötigen würden) dürften dabei ja nicht
vorkommen.
Oliver
Oliver S. schrieb:> Da kommt wirklich der Dezimalwert des Hex-Wert in einem int? Wer macht> denn sowas?
RTC-Uhren machen sowas.
Udo S. schrieb:> Lothar M. schrieb:>>> Wie kriege ich jetzt die 54[Hex] in eine 54[Dec] gewandelt?>>>> Eine Wandlung ist evtl. gar nicht nötig, denn das ist beide Males die>> selbe Bitfolge: "0101_0100". Nur jeweils anders dargestellt.> Ich denke Lothar hat recht.
Sorry, ich habe meinen Post gelöscht, weil ich nach wiederholtem Lesen
der Beschreibung vermute (wie Michael O. auch), dass da tatsächlich ein
Packed-BCD-Wert ankommt.
EDTI: allgemein bekannt ist die Lösung als "bcd2bin". Da gibts dann
einige Google-Treffer. Speziell auch im Bezug auf RTC:
*
https://cpp.hotexamples.com/examples/-/-/BCD2BIN/cpp-bcd2bin-function-examples.html
Lothar M. schrieb:> Sorry, ich habe meinen Post gelöscht, weil ich nach wiederholtem Lesen> der Beschreibung vermute (wie Michael O. auch), dass da tatsächlich ein> Packed-BCD-Wert ankommt.
Sage ich ja auch :-)
Die Postings haben sich nur überschnitten.
Ist bestimmt gepacktes BCD, und das Anzeigeprogramm des TO nimmt es
fälschlicherweise als binären Bytewert.
John P. schrieb:> ich kriege die Sekunden von einer App als Hex Wert gesendet.>> Beispiel: 54 sec>> wird gesendet als int mit Wert 84[Dec]
Ja, was denn nun? Einmal sagst Du, die gesendeten Werte seien
Hex-Zahlen. Dann wiederum sagst Du es seien Dezimalzahlen.
Entscheid Dich mal. Oder ist es am Ende weder noch, sondern das
BCD-Format wie hier manche vermuten?
Oliver S. schrieb:> Da kommt wirklich der Dezimalwert des Hex-Wert in einem int? Wer macht> denn sowas?Lothar M. schrieb:> RTC-Uhren machen sowas.
Genau so sieht es aus. Damit wurde eine RTC gestellt.
Die RTC soll nun in Software abgebildet werden. Und die Software
erwartet Dezimal werte.
Oliver S. schrieb:> Wenns wirklich so ist, rechne halt zu Fuß um: abs(84/16) *10 + Rest *16
Geil! Vielen Dank auf sowas hatte ich gehofft.
Kurz nachgerechnet passt es.
Ich probiere es gleich mal aus.
Udo S. schrieb:> Sage ich ja auch :-)
Nur hattest Du keine Lösung dazu geschrieben.
@TO: Die (jetzt) oberst Antwort ist richtig und gut. Alles weiteren in
Summe eher verwirrend.
John P. schrieb:> Oliver S. schrieb:>> Wenns wirklich so ist, rechne halt zu Fuß um: abs(84/16) *10 + Rest *16>> Geil! Vielen Dank auf sowas hatte ich gehofft.> Kurz nachgerechnet passt es.> Ich probiere es gleich mal aus.
???
Sollte das nicht eher (84/16)*10+Rest sein?
Also (84/16)×10+84%16 oder gleichwertig
Michael O. schrieb:> OutVal = (BCDVal >> 4) * 10 + (BCDVal & 0x0F);
A. S. schrieb:> Sollte das nicht eher (84/16)*10+Rest sein?>> Also (84/16)×10+84%16 oder gleichwertig
genau. Mit deder Multiplikation des Restes der Division mit 16 muss es
natürlich schief gehen. und das abs() tut auch nicht Not. Sollte ja
alles positiv sein :-)
Und um die (rechenintensivere) Division mit Restbildung zu umgehen
shiftet man einfach die oberen 4 bit nach rechts und maskiert die oberen
4 bit für die Addition der Einerstelle aus.
Gruß Micha
Michael O. schrieb:> Und um die (rechenintensivere) Division mit Restbildung zu umgehen> shiftet man einfach die oberen 4 bit nach rechts und maskiert die oberen> 4 bit für die Addition der Einerstelle aus.
Jeder wie er mag, der Compiler macht (bei unsigned skalaren) den
gleichen Code raus.
Oliver S. schrieb:> Da kommt wirklich der Dezimalwert des Hex-Wert in einem int? Wer macht> denn sowas?
Nennt sich BCD, eine kompakte Darstellung für mehrstellige
Dezimalzahlen, die leicht nibble-weise zu dekodieren ist, z.B. auch
direkt per Hardware mit dem 74xx47.
"Die Funktion nutzt eine Schleife, um durch die Ziffern der
Hexadezimalzahl zu iterieren. Sie nimmt die letzte Ziffer der
Hexadezimalzahl, indem sie den Rest von hex durch 10 dividiert, und fügt
sie zur Dezimalzahl hinzu. Dann teilt sie hex durch 10, um zur nächsten
Ziffer zu gelangen. Die Schleife wird fortgesetzt, bis hex 0 ist."
Wegstaben V. schrieb:> John P. schrieb:>> als Hexadezimalen string zu printen>> uh, jetzt hab ich etwas Augenweh aufgrund dieser verdenglischiung "zu> printen" ;-)
geht nicht nur dir so.
aber ich wollte damit auf printf() hinweisen. Und die Funktion gibt
nunmal nicht als ausgabef() ;)
Leo schrieb:> hex_bcd_to_decimal
Das Ding macht aber nicht, was der Funktionsname vermuten lässt, sondern
die Funktion wandelt Binär/Dezimal (die Bitmuster sind ja für Binär- und
Dezimalzahlen sowieso gleich) nach Packed-BCD.
Sie sollte also bin_to_bcd oder decimal_to_bcd (oder eben wie üblich
kurz bin2bcd) heißen, und zum Schluss müsste somit stehen "return bcd;"
Ja, dass man den Mod-Wert, bzw. die einzelnen Mod-Werte bei der
Umwandlung auf den Stack pushen kann, bzw. in einen String schieben, um
dann die Liste der Modwerte umgekehrt nach oben auszulesen, ist hier ein
wenig untergegangen, oder nicht?
Ein anderer Punkt ist, bei so Uhren müsste man eigentlich noch zu einem
60er System übersetzen.
50/80 ist deswegen schwierig (bzw. sehr leicht), weil die Zahlensysteme
(also hier Hexi und Dezi) gewisse Ähnlichkeiten haben. Ich vermute mal,
diese Zusatzinfogeschichte hat die Verwirrung ausgelöst. Ist ja auch
nicht uninteressant ;)
Die Hexwerte selber helfen, sofort die Bitwerte zu sehen. Man könnte
also auch von den Bits her nach Dezi übersetzen.
Oder eben erstmal von Hex nach Bits.
BCD-Zahlen sind noch mal eine ganz andere Rechnung. Das sind einfach die
nomalen Dezimalen Zahlen also solche im Rechner abgebildet. ABCDEF (wie
im Hexadezimalsystem gibt es da nicht und die Umrechnung ist aufwendig,
aber teilweise gibt es Hardwarebeschleunigungen.
Was hier auch noch fehlt, wären ein paar Zusatzbeispiel für die Ausgabe.
Bei 54/84 sehe ich nur Hex/Dez-Werte und eine ungefragte Konvertierung -
was ja nun auch der ghci so gerne macht, wenn man einfach mit Hexwerten
rechnen möchte.
Leo schrieb:> Und das macht ChatGPT bei BCD to Dez:> ...
Die Funktion bcd_to_decimal kann optimiert werden zu
1
intbcd_to_decimal(intbcd){
2
returnbcd>0?bcd:0;
3
}
Was war denn diesbezüglich deine Anfrage an ChatGPT? Der Funktionsname
(bcd_to_decimal) klingt ja im Zusammenhang mit der Signatur (int -> int)
schon etwas unsinnig.
Wegstaben V. schrieb:> John P. schrieb:>> als Hexadezimalen string zu printen>> uh, jetzt hab ich etwas Augenweh aufgrund dieser verdenglischiung "zu> printen" ;-)
Printen esse ich gerne.
rbx schrieb:> 50/80 ist deswegen schwierig
Besser wären evtl. 49 Sekunden = 0x49 = 01001001bin = 73dez gewesen...
Yalu X. schrieb:> Die Funktion bcd_to_decimal kann optimiert werden
Sollte wohl bcd /= 16; statt bcd /= 10; heißen...
(int -> int)
Ich würde dann wenigstens unsigned int erwartet. Denn BCD-Zahlen an sich
können nicht negativ sein.
Lothar M. schrieb:> rbx schrieb:Lothar M. schrieb:> Yalu X. schrieb:John P. schrieb:> ich hab eine Denkblockade.
Und der ganze Thread bloß weil der John sein Gehirn nicht angeworfen
gekriegt hatte. Es ist wirklich erschreckend, wie sehr es hier an
Grundlagenwissen fehlt. Aber ungeachtet dessen wollen eben dieselben
Leute mit ihrem Steckbrett, Arduino oder ST-Cube-Zeugs zum Mond fliegen
oder etwas gleichgroßes veranstalten. und unter
C.K. schrieb:> https://cplusplus.com/reference/cstdlib/strtol/
macht man's heutzutage nicht mehr.
W.S.
> Aber ungeachtet dessen wollen eben dieselben> Leute mit ihrem Steckbrett, Arduino oder ST-Cube-Zeugs zum Mond fliegen> oder etwas gleichgroßes veranstalten. und unter> C.K. schrieb:>> https://cplusplus.com/reference/cstdlib/strtol/>> macht man's heutzutage nicht mehr.> W.S.
Genau, weil deine Betyy mit USB Code es jemals weiter als 10km in die
Höhe schafft.
W.S. schrieb:> unter>> C.K. schrieb:>> https://cplusplus.com/reference/cstdlib/strtol/>> macht man's heutzutage nicht mehr.
Die Frage es TE war zwar unpräzise formuliert, aber mittlerweile dürfte
klar sein, dass er nicht nach strtol gesucht hat:
John P. schrieb:> A. S. schrieb:>> Michael O. schrieb:>>> OutVal = (BCDVal >> 4) * 10 + (BCDVal & 0x0F);>> Das funktioniert.
Darf ich noch was aus dem ghci nachreichen? Nur um Missverständnisse zu
vermeiden (man kann nämlich leicht durcheinanderkommen). Bei kleinen
Werten braucht man nur durch 16 teilen und den Rest draufzählen.
1
[rbx@fe1 ~]$ ghci
2
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
3
Prelude> let hexzuruk ab = (div ab 16, mod ab 16)
4
Prelude> hexzuruk 84
5
(5,4)
6
7
Prelude> hexzuruk 73
8
(4,9)
Da darf man dann nicht vergessen/übersehen, dass da normalerweise noch
abcdef kommt, die aber bei bei dieser Art von Rückkonvertierung kaum
noch eine Rolle spielen.
Früher hat man Uhren oder DCF77-Decoder noch ohne MC und nur mit TTL-ICs
gemacht. Daher das gepackte BCD-Format.
Irgendwie kriegt man das aus den Hirnen aber nicht wieder raus, daher
ist es selbst in den neuesten MCs noch drin.
Daher muß jeder PC beim Einschalten erstmal das veraltete BCD-Format aus
der RTC lesen und in 64Bit Sekunden umrechnen.
Nur ganz wenige RTCs haben 32Bit oder 64Bit Sekunden für direkte
Verarbeitung (Vergleiche, Zeitstempel von Dateien usw.).
noch eine MöglichkeitVariante ...
// bcd to dec format and reverse
//#define mBcd2Bin(b) (((b)>>4)*10+((b)&0x0F))
#define mBcd2Bin(b) ((b)-6*((b)>>4))
#define mBin2Bcd(b) ((b)+6*((b)/10))
rbx schrieb:> Darf ich noch was aus dem ghci nachreichen?
Warum? Der TE suchte nach eine Lösung in C und die hat er längst
bekommen.
Aber wenn schon Haskell, dann machen wir das mal richtig :)
> Prelude> let hexzuruk ab = (div ab 16, mod ab 16)
Div und mod kann man zusammenfassen:
1
hexzuruk ab = divMod ab 16
> Prelude> hexzuruk 84> (5,4)
Der TE will das Ergebnis nicht als Paar von zwei Ziffern, sondern als
eine Integerzahl (im konkreten Fall 54). Das würde dann bspw. so
aussehen:
1
bcd2bin bcd = 10 * high + low
2
where (high, low) = divMod bcd 16
Die Umkehrfunktion wäre entsprechend
1
bin2bcd bin = 16 * high + low
2
where (high, low) = divMod bin 10
Wenn man möchte, kann man das auch pointfree (also ohne explizites
Funktionsargument) schreiben und dabei zudem die Hilfsvariablen high und
low eliminieren:
Natürlich könnte die Zerlegung des BCD-Bytes in zwei Nibbles statt mit
einer Division auch mit shiftR und .&. erfolgen, aber das war dir wohl
zu C-ish ;-)
Yalu X. schrieb:> aber das war dir wohl> zu C-ish ;-)
Eigentlich nicht, ich weiß ja, wie man es in asm macht. Aber das
Beispiel mit dem uncurry finde ich schon gut. Auch wenn es natürlich die
Schwierigkeit bis Unmöglichkeit der Übersetzung ein wenig verschleiert.
Die Frage ist doch: wenn die Ausgangszahlen Dezimalzahlen sind, warum
bleiben die das nicht?
Zahlensysteme sind immer eindeutig. Doppelte Zahlen kommen da nicht vor.
Die hätte man aber, wenn man abcdef nicht konkret berücksichtigt. 74 ist
nicht 50, sondern 7A.
Mir ging es eher darum, darauf hinzuweisen, wie man Denkblockaden
umgehen kann, beim Hin - und Herkonvertieren nicht durcheinander kommt,
und die gelegentliche Schönheit des Hexadezimalsystems nicht übersieht,
und ansonsten auch nur um ein wenig Austausch und die Dinge nicht allzu
ernst nehmen ;)
rbx schrieb:> 74 ist> nicht 50, sondern 7A.
Was natürlich auch schon wieder Unfug ist..nix 7A - 4A war gemeint,
entschuldigung.
(man kann durcheinander kommen..)
(7A war der Jump nach oben)
Das macht es auch nicht besser.
Wenn man das ausgiebt kommt "J" heraus.
Meine Kenntnisse in C sind rudimentär.
Aber es sollten doch einfache Anweisungen zur Umwandlung von
Datenformaten geben.
Selbst in Assembler genügen da weniger als 10 Zeilen.
John P. schrieb:> ich kriege die Sekunden von einer App als Hex Wert gesendet.>> Beispiel: 54 sec>> wird gesendet als int mit Wert 84[Dec] was einer 54[Hex] entspricht.>> Wie kriege ich jetzt die 54[Hex] in eine 54[Dec] gewandelt?
Mir wird da ganz schwindelig.
Welche APP?
Wie sieht die Bytefolge konkret aus?
Vermutlich wird BCD geschickt.
54H/84Dec ergibt "T".
michael_ schrieb:> Meine Kenntnisse in C sind rudimentär.> Aber es sollten doch einfache Anweisungen zur Umwandlung von> Datenformaten geben.
mit printf geht da so einiges..
Man muss aber auch unterscheiden zwischen Zahlensystemen, und
Ausgabegeschichten (ASCII)/printf etc. oder Abbildungsstrategien im
Rechner (BCD z.B.).
54Hex nach 54Dez geht sowieso schlecht und macht auch keinen Sinn.
BCD-Zahlen haben eine ganz eigene Rechnerei.
Echt was für µc-Profis.
Am sichersten ist es, wenn es von Hex nach BCD geht, erst nach Dez
(durch "A" teilen..) und diese Resultate dann als BCD behandeln - und
dass ist bei Intel-Asm einfach, hat halt eine eigene Unterabteilung.
Aber auch nur für die Rechnerei.
Bei DOS kommt die Zahl aus dem "Rechen-Register" typischerweise nach DL,
und von da aus wird dann 30 draufgezählt für die Ausgabe per
ASCII-Codierung.
Völlig egal, ob aus dem Rechenregister für BCD-Zahlen, oder ob aus einem
normalen Register. Zahl bleibt Zahl bzwl. eine 7 bleibt eine 7, eine 6
bleibt eine 6, eine 5 bleibt eine 5..
Da aber auch die Problembeschreibung / Ist/Soll vom TE oben nicht ganz
durchsichtig bzw. logisch ist, denke ich mal das ist ein Teil des
Problems an sich: Die Zusammenhänge des Geschehens nicht so recht
durchblicken.
Oft soll es ja schon helfen, das Problem zu verstehen, wenn man die
Frage etwas genauer formulieren kann.
michael_ schrieb:> Das macht es auch nicht besser.> Wenn man das ausgiebt kommt "J" heraus.
4A ist die Hexzahl für 74. 0111 0100 - Der ASCII-Code für 4A ist
typischerweise 0011 0100 0100 0001 und hat nichts mit dem Zahlensystem
zu tun, sondern nur mit der Ausgabe.
7A war der Hexwert für den ASM-Befehl JA - welcher Jump if above meinte.
Ich hatte das deswegen durcheinander gebracht, ganz genau weil gewisse
Dinge so merkwürdig sind: 7A, JA - 4A, J (Ja Ja..). - 4B -> K (ASCII)
4C -> L(ASCII).