Binärzahlen2
-
Ick hab auch mal ein bisschen mit C++ rumgespielt.
Folgendes Progrämmchen wandelt Zahlen in eine beliebige Darstellung zwischen Base2 und Base37 um:
#include <iostream> using namespace std; string toBase (int base, int num) { static string charset = "0123456789abcdefghijklmnopqrstuvwxyz"; if (!num) return ""; return toBase(base, num/base) + charset[num%base]; } int main() // test { cout << toBase (10, 27) << endl; // 27 dez. cout << toBase (2, 27) << endl; // 27 binär cout << toBase (16, 27) << endl; // 27 hex cout << toBase (8, 27) << endl; // 27 oktal cout << toBase (5, 27) << endl; // 27 in base 5 }
-
0 geht nicht.
-
SeppJ schrieb:
0 geht nicht.
Negative Zahlen auch nicht.
Und Brüche erst recht nicht.
-
Andromeda schrieb:
SeppJ schrieb:
0 geht nicht.
Negative Zahlen auch nicht.
Und Brüche erst recht nicht.Negative Zahlen sind bei den meisten Anfängerübungsaufgaben ausgenommen, um es nicht zu kompliziert zu machen. Aber korrekte Behandlung der 0 sollte man erwarten. Ist ein guter Test, ob der Programmierer mitdenkt, denn die offensichtliche Lösung - deine - kann die 0 nicht richtig.
-
SeppJ schrieb:
Andromeda schrieb:
SeppJ schrieb:
0 geht nicht.
Negative Zahlen auch nicht.
Und Brüche erst recht nicht.Negative Zahlen sind bei den meisten Anfängerübungsaufgaben ausgenommen, um es nicht zu kompliziert zu machen. Aber korrekte Behandlung der 0 sollte man erwarten. Ist ein guter Test, ob der Programmierer mitdenkt, denn die offensichtliche Lösung - deine - kann die 0 nicht richtig.
Gut, ich fühle mich schuldig und schiebe ein Update nach, das die 0 und negative Zahlen verarbeiten kann, sowie auch eine falsche Basis abfängt.
#include <iostream> using namespace std; string charset = "0123456789abcdefghijklmnopqrstuvwxyz"; string toBaseKernel (unsigned int base, int num) { if (!num) return ""; return toBaseKernel(base, num/base) + charset[num%base]; } string toBase (unsigned int base, int num) { if (!num) return "0"; if (base < 2 || base > charset.size()) return "invalid base"; char sign = '+'; if (num < 0) { sign = '-'; num = -num; } return sign + toBaseKernel (base, num); } int main() // test { cout << toBase (36, -35) << endl; ... ... }
-
Andromeda schrieb:
num = -num;
Das kann auf Systemen mit Zweierkomplement Probleme bei INT_MIN machen.
(Ich habe nicht überprüft, wie sich toBaseKernel bei negativen Werten verhält)SeppJ schrieb:
Negative Zahlen sind bei den meisten Anfängerübungsaufgaben ausgenommen, um es nicht zu kompliziert zu machen.
-
DirkB schrieb:
Andromeda schrieb:
num = -num;
Das kann auf Systemen mit Zweierkomplement Probleme bei INT_MIN machen.
Okay, also müssen wir womöglich dem Wertebereich einen Wert wegnehmen. Du bist echt ein Erbsenzähler, Mann. Schau dir mal Implementationen von abs() an. Vielleicht bringt uns das weiter.
DirkB schrieb:
(Ich habe nicht überprüft, wie sich toBaseKernel bei negativen Werten verhält)
Sei dir sicher: absolut garstig.
-
Andromeda schrieb:
Schau dir mal Implementationen von abs() an.
abs
darf das, weil es so in den Spezifikationen steht. Es geht ja auch gar nicht anders,abs(INT_MIN)
kann auf gängigen Systemen eben einfach nicht alsint
repräsentiert werden. Aber wenn wir hier schon einen eigenen Zahlensystemprinter schreiben, dann sollte auch der Anspruch bestehen, es sowohl möglichst schön, funktionierend für alle Zahlen, und absolut sicher gegenüber jedweder Erbsenzählerei zu machen.Wir wollen schließlich etwas dabei lernen, oder? Jedenfalls hatte ich mit den Standardmitteln noch keine Schwierigkeiten, INT_MIN auszugeben.
-
SeppJ schrieb:
Aber wenn wir hier schon einen eigenen Zahlensystemprinter schreiben, dann sollte auch der Anspruch bestehen, es sowohl möglichst schön, funktionierend für alle Zahlen, und absolut sicher gegenüber jedweder Erbsenzählerei zu machen.
Naja, ick wollte halt nur eine einfache, rekursive Funktion zeigen, die Zahlen in einem beliebigen Stellenwertsystem ausgeben kann. Auf Plausibilitätsprüfungen legte ich erstmal keinen Wert. Das lenkt eigentlich nur ab.
-
Bei Dualzahlen interessiert mich eigentlich auch nur das Bitmuster von dem Wert, bzw. dessen hexadezimale oder oktale Darstellung.
Das Vorzeichen möchte ich nicht wissen.SeppJ schrieb:
Wir wollen schließlich etwas dabei lernen, oder? Jedenfalls hatte ich mit den Standardmitteln noch keine Schwierigkeiten, INT_MIN auszugeben.
Wie verhält sich eigentlich
cout
bei Hexdarstellung und Typen mit Vorzeichen?
printf
nimmt da eigentlich nurunsigned
Typen.Andromeda schrieb:
Naja, ick wollte halt nur eine einfache, rekursive Funktion zeigen, die Zahlen in einem beliebigen Stellenwertsystem ausgeben kann.
Ist ok. Die Eingrenzung auf positive Werte ist auch ok. Aber die 0 wurde (zu Recht) angemeckert.
Du hättest dann auch als Paramter einen unsigned Typen nehmen sollen.Andromeda schrieb:
Auf Plausibilitätsprüfungen legte ich erstmal keinen Wert. Das lenkt eigentlich nur ab.
Aber das ist die Kunst.
-
DirkB schrieb:
Andromeda schrieb:
Auf Plausibilitätsprüfungen legte ich erstmal keinen Wert. Das lenkt eigentlich nur ab.
Aber das ist die Kunst.
Das ist zweifellos eine Kunst. Aber eine separate Kunst, die mit dem eigentlichen Algorithmus nicht viel zu tun hat.
Wie in meinem zweiten Beispiel, kann man Plausibilitätsprüfungen und ein Geradebiegen der Eingangsdaten meistens in ein vorgeschaltetes Modul verlagern. Oder man setzt assert() ein. Ick weiß aber nicht ob das in C++ üblich ist, oder ob man besser Exceptions verwenden soll.
Kennt noch jemand Windows NT 4.0? Das hatte einen sehr schlechten Ruf, weil die Entwickler auf Fehlerchecks im User-Mode verzichteten. So landete der Fehler letztlich beim OS selbst, und das konnte nur noch mit einen Crashdump antworten und das ganze System anhalten.
Btw, sorry für das Off-Topic.