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.
Parameter: Input: Die Bases der Zahl, bei Hex ist es 16
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.
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:
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.
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.
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.
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."
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.
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.
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
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:
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))
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 ;-)
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 ;)
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.
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.
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).