Zahlenfolge umkehren
-
Also ich habe heute an der Uni übungen zu c++ bekommen, bin da selbst neu (2 -3 Tage) und soll nun eine dezimalzahl in eine binärzahl umwandeln bisher habe ich folgenden code:
// long zahl1.cpp: Hauptprojektdatei. #include "stdafx.h" #include "iostream" using namespace std; int main() { long d; int bi; cout << "Geben Sie eine Zahl ein !" << endl; cin >> d; cout << "Ihre Dezimalzahl lautet: "; while(d>=1) { bi=d%2; cout << bi; d/=2; } cout << endl; system("PAUSE"); return 0; }
Ich weis, dass das vermutlich ganz schön umständlich oder von mir aus auch schlecht ist, aber dafür komplett auf meinem Mist gewachsen :-P. Jetzt bekomme ich aber eben immer die "umgekehrte" Binärzahl raus bei 19 wäre dass z.B. :
11001 statt der 10011.Meine frage ist nun, wie kann ich das ganze rumdrehen, ich habe mir da ettliche sachen durchgelesen aber das hat alles nicht so richtig funktioniert, also ich war scheinbar noch zu ungebildet das umzusetzen oder zu begreifen, weil ich will ja nicht blos kopieren sondern auch eben verstehen.
Wäre klasse wenn mir da mal jemand eine Hilfestellung geben könnte, wie man die Zahl relativ simpel umdrehen könnte.
MFG
Arakos
-
Zwei Vorschläge wie man so etwas machen könnte:
1. Technische Lösung: Du musst dir die Werte merken. Dann kannst du sie hinterher einfach umgekehrt ausgeben. Die Sprachmittel zum Zwischenspeichern einer zuvor unbekannten Anzahl von Werten sind in deinem Kurs wohl noch nicht drangekommen, sonst würdest du nicht fragen müssen (ein mögliches Mittel wäre std::vector).
2. Mathematische Lösung: Du könntest zunächst einmal rausfinden, wie groß die Zahl ungefähr ist, d.h. die Wertigkeit der höchsten Stelle im Binärsystem suchen (konkret: Ist sie >=1? Falls ja, ist sie >=2? Falls ja, >= 4? Falls ja, >=8? usw.). Dann kannst du von dieser Stelle an dein Schema, so wie du es jetzt hast, rückwärts durchgehen.
-
Es sind "long" zahlen also is der höchste wert 2.147.483.647 wenn ich net irre ... und dich richtig verstanden habe, ich weis also net ob der mathematische weg lohnt und wie funktioniert das mit dem vector, wäre die zweite frage.
-
Versuche den Code, den Du hast, in eine Funktion zu packen. Ändere die Funktion so ab, das lediglich die letzte (also niederwertigste) Binärstelle berechnet, aber zunächst nicht ausgegeben wird (bi). Teile dann den Wert (d) durch 2 und rufe die gleiche Funktion auf, falls d noch >0 ist. Anschließend gibst Du das oben gemerkte niederwertigste Bit aus.
Das ganze nennt man Rekursion.Gruß
Werner
-
Werner Salomon schrieb:
Versuche den Code, den Du hast, in eine Funktion zu packen. Ändere die Funktion so ab, das lediglich die letzte (also niederwertigste) Binärstelle berechnet, aber zunächst nicht ausgegeben wird (bi). Teile dann den Wert (d) durch 2 und rufe die gleiche Funktion auf, falls d noch >0 ist. Anschließend gibst Du das oben gemerkte niederwertigste Bit aus.
Das ganze nennt man Rekursion.Gruß
WernerTut mir leid wenn ich auf nem Schlauch stehe, aber ich habe gerade "Rekursion" gegooglet und ich weiß nicht wie ich hinten anfangen könnte, da das ja das Kriterium meiner Schleife ist ?! Vl bin ich auch einfach zu müde ich weises net.
-
Gut, dann ein Beispiel ohne Rekursion:
std::cout<<"\nZahl eingeben: "; unsigned long number; std::cin >> number; unsigned long msb = 1ul; while (number >= msb) msb<<=1; msb>>=1; while (msb) { std::cout<<((number&msb)!=0); msb>>=1; }
Nicht schick, aber ist ja auch schon spät.
-
inter2k3 schrieb:
Gut, dann ein Beispiel ohne Rekursion:
std::cout<<"\nZahl eingeben: "; unsigned long number; std::cin >> number; unsigned long msb = 1ul; while (number >= msb) msb<<=1; msb>>=1; while (msb) { std::cout<<((number&msb)!=0); msb>>=1; }
Nicht schick, aber ist ja auch schon spät.
Also ich danke für die funktionierende lösung, habe jedoch keine Ahnung wie das funktioniert:
std::cout<<"\nZahl eingeben: "; //Aufforderung zur Eingabe unsigned long number; //number definieren std::cin >> number; //--> eingeben unsigned long msb = 1ul; //msb (höchstwertiges bit?!) wird //definiert =1ul (1. Was ist 1ul,was macht es //und was bedeutet es? while (number >= msb) //Schleife solange bis number größergleich msb msb<<=1; //2. was macht das? es zählt oder ?! KA! msb>>=1; //3. was macht das? while (msb) { //noche ne schleife die ich komplett //net verstehe std::cout<<((number&msb)!=0); msb>>=1; }
Grüße und vielen dank für die schnelle Hilfe, aber ich muss eine Lösung vorm prof auch vertreten können :S
wünsche eine gute nacht und wenn jemand grade nichts zu utun hat kann er ja evt nen gut deutschen pseudocode draus machen
Gn8 !!
-
Arakos schrieb:
unsigned long msb = 1ul; //msb (höchstwertiges bit?!) wird //definiert =1ul (1. Was ist 1ul,was macht es //und was bedeutet es?
Richtig, msb = most significant bit.
Dieses wird hier erstmal auf 1 gesetzt (entspricht binaer also 0....001). Das ul (präfix) gibt nur den Typ an (unsigned long). Dies wäre nicht nötig, du kannst auch einfach 1 schreiben (dann erfolgt ein impliziter cast - aber das alles ist in dem Zusammenhang jetzt auch eher unwichtig).Arakos schrieb:
while (number >= msb) //Schleife solange bis number größergleich msb msb<<=1; //2. was macht das? es zählt oder ?! KA!
Solange die eingegebene Zahl (number) grösser oder gleich msb ist wird der Wert von msb um eins nach links geshiftet (bitweise Operation).
Ich lass jetzt mal die ganzen Nullen für unsigned long weg und nehme einfach mal nur 8 bits als beispiel:0000 0001 - ist logischerweise 1
shifte ich jetzt um eins nach links, wird jedes bit wie der Name schon sagt um eine Position nach links verschoben. Das Resultat ist dann.
0000 0010 - was dem Wert 2 entspricht
Shiftest du nun wieder erhälst du? ... -> richtig, 4, dann 8, 16 ...Anderes Beispiel:
0001 1001 - Wert 25
Um 3 nach rechts geshiftet ergibt:
0000 0011 - Wert 3 (man beachte, dass das LSB [1 ganz rechts] rausgeflogen ist).
Soviel zum bitshiften erstmal.Arakos schrieb:
msb>>=1; //3. was macht das?
Shift um eins nach rechts. Warum? Wenn du eine 19 eingegeben hattest, ist diese erstmal grösser als 1,2,4,8 und 16. Jedesmal wird MSB um eins nach links geshiftet (s.o.). Allerdings ist 19 mit 5 bits darstellbar - msb hat aber jetzt den Wert 32 (6 bits) - also shifte ich wieder eins zurück, damit nachher keine führende 0 dargstellt wird (das war der Punkt, warum ich "nicht schick" geschrieben habe
)
Arakos schrieb:
while (msb) { //noche ne schleife die ich komplett //net verstehe std::cout<<((number&msb)!=0); msb>>=1; }
Solange msb nicht 0 ist (jede Zahl ungleich 0 wird bei einem cast zu einem boolschen Wert true, nur die 0 wird fals) wird die Schleife durchlaufen.
Was gebe ich in der Schleife aus?
Das Zeichen & ist wieder eine bit-Operation (bitweises und). Damit werden also zwei Zahlen bitweise verglichen, und überall wo beide Zahlen eine eins stehen haben, hat auch das Ergebnis eine eins stehen.
Kleines Beispiel (19 & 16)
0001 0011 &
0001 0000
---------
0001 0000 (Ergebnis also 16)
(number&msb) wird also zu einer Zahl ausgewertet, die genau die gleiche ist wie msb, wenn number an der Stelle, an der msb die 1 stehen hat auch eine 1 hat. Falls number dort keine 1 stehen hat, ist das Ergebnis logischerweise 0.
Eigentlich könntest du das Ergebniss nun einfach zu einem boolschen Wert casten, oder du vergleichst es einfach mit 0 (was ich oben tue) - kommt im Endeffekt aufs gleiche raus.Hm - wenn man noch nie mit Bit-Operatoren gearbeitet hat, ist das sicherlich verwirrend.
-
Falls das nun zu kompliziert war, hier noch ein kleines Beispiel mit dem angesprochenen vector:
#include <vector> // nicht vergessen // Der vector bin speichert int werte (koenntest auch bool nehmen oder short oder was weiss ich) std::vector<int> bin; std::cout<<"\nZahl eingeben: "; unsigned long number; std::cin>>number; while (number) { // modulo kennst du ja schon. Der Wert wird jetzt einfach im Vektor gespeichert bin.push_back(number%2); // Zahl nun durch 2 geteilt - denke ich ist klar - hast du ja auch so gemacht number/=2; } // Jetzt muessen noch alle Werte in umgekehrter Reihenfolge ausgegeben werden. // Ich iteriere über alle gespeicherten Werte, allerdings hinten beginnend und gebe diese einfach aus // Wuerde nun allerdings ein wenig den Rahmen sprengen zu erklären was Iteratoren sind, wie sie funktionieren, was rbegin() und rend() etc. machen for (std::vector<int>::const_reverse_iterator it = bin.rbegin(), end = bin.rend(); it != end; ++it) std::cout<<*it;
-
Da bietet sich doch eher ein Stack an, als ein Vektor, oder?
-
Die Rekursionslösung sieht übrigens in etwas so aus:
void print_binary(int num) { if(num == 0) return; int last_digit = num % 2; print_binary(num / 2); cout << last_digit; }
-
Vielen dank für die ausführlichen Erläuterungen ! Ich hab sogar ein bisschen mehr urchblick als vorher, ich hatte mir sowas wie das mit den Vectoren schon überlegt und bin dabei aber bei "strings" und "sstreams" gelandet nur rleide konnte ich keine zahlen darin aufnehmen geschweige denn das ganze umdrehen, ich denke ich nehme die Iteration und den Vector, da das mit den Bitoperationen sicherlich der "perfektere" aber nicht der "anfänger " weg sein kann
aber trotzdem danke für das ausführliche erklären das hilft schon enorm.
Gruß Arakos
-
Wie Belli schon sagt eignet sich hier natürlich auch ein stack sehr gut (wegen LIFO).
Kannst du ja erstmal alleine versuchen umzusetzen und ggf nochmal fragen.
-
Kann jemand ein gutes Script für c++ nennen, dass sich zwecks dünnen studentengeldbeutels online anschauen lässt ? wenn ich z.B. Stacks google dann kommen da auch tolle themen, aber vom grunde her erklärt is da sehr wenig.
Gruß Arakos
-
Igitt! "Script für C++"
Es heißt Programm!
-
ich meinte einen ordentlichen Guide ein Tut oder ähnliches^^ !
Btw ich benutze Visual C++ 2010 Express und habe nun folgenden Code mit einem Stack, da diese Methode wirklich sehr einleuchtend ist:
// long zahl1.cpp: Hauptprojektdatei. #include "stdafx.h" #include "iostream" #include "stack" using namespace std; int main() { stack(int) binstack; long d; int bi; cout << "Geben Sie eine Zahl ein !" << endl; cin >> d; while(d>=1) { binstack push (bi=d%2); d/=2; } cout << "Ihre Dezimalzahl lautet: "; while(!binstack.empty()) { printf("%d ", binstack.top()); binstack.pop(); } cout << endl; system("PAUSE"); return 0; }
Wobei ich folgenden Fehler erhalte:
1>------ Erstellen gestartet: Projekt: long zahl1, Konfiguration: Debug Win32 ------
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: Der Buildvorgang wurde aufgrund eines internen Fehlers unerwartet beendet.
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: Microsoft.Build.Exceptions.BuildAbortedException: Der Buildvorgang wurde abgebrochen. "MSBuild.exe" konnte nicht als untergeordneter Knoten gestartet werden, da die Datei nicht am Speicherort "C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" gefunden wurde. Geben Sie den korrekten Speicherort ggf. in den BuildParameters oder mit der MSBUILD_EXE_PATH-Umgebungsvariable an.
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.BackEnd.NodeManager.AttemptCreateNode(INodeProvider nodeProvider, NodeConfiguration nodeConfiguration)
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.BackEnd.NodeManager.CreateNode(NodeConfiguration configuration, NodeAffinity nodeAffinity)
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.PerformSchedulingActions(IEnumerable`1 responses)
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.HandleNewRequest(Int32 node, BuildRequestBlocker blocker)
1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.IssueRequestToScheduler(BuildSubmission submission, Boolean allowMainThreadBuild, BuildRequestBlocker blocker)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========<.< das sagt mir nix mit den bisherigen fehlern konnte ich noch was anfangen, aber das ?!
Gruß Arakos
-
Möglicherweise hilft dir Aufbau der STL weiter.
Dein Progrämmchen sieht ja schon fast richtig aus.
Ich korrigier es mal eben:// long zahl1.cpp: Hauptprojektdatei. #include <iostream> #include <stack> using namespace std; int main() { stack<int> binstack; long d; cout << "Geben Sie eine Zahl ein !" << endl; cin >> d; while(d>=1) { binstack.push(d%2); d/=2; } cout << "Ihre Dezimalzahl lautet: "; while(!binstack.empty()) { cout<<binstack.top(); binstack.pop(); } cout << endl; system("PAUSE"); return 0; }
-
Copy + Paste bringt mir foglgenden Text:
Fehlercode:
1>------ Erstellen gestartet: Projekt: long zahl1, Konfiguration: Debug Win32 ------ 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: Der Buildvorgang wurde aufgrund eines internen Fehlers unerwartet beendet. 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: Microsoft.Build.Exceptions.BuildAbortedException: Der Buildvorgang wurde abgebrochen. "MSBuild.exe" konnte nicht als untergeordneter Knoten gestartet werden, da die Datei nicht am Speicherort "C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" gefunden wurde. Geben Sie den korrekten Speicherort ggf. in den BuildParameters oder mit der MSBUILD_EXE_PATH-Umgebungsvariable an. 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.BackEnd.NodeManager.AttemptCreateNode(INodeProvider nodeProvider, NodeConfiguration nodeConfiguration) 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.BackEnd.NodeManager.CreateNode(NodeConfiguration configuration, NodeAffinity nodeAffinity) 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.PerformSchedulingActions(IEnumerable`1 responses) 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.HandleNewRequest(Int32 node, BuildRequestBlocker blocker) 1>C:\Users\EpoX\Documents\Visual Studio 2010\Projects\long zahl1\long zahl1\long zahl1.vcxproj : error MSB4014: bei Microsoft.Build.Execution.BuildManager.IssueRequestToScheduler(BuildSubmission submission, Boolean allowMainThreadBuild, BuildRequestBlocker blocker) ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
Gruß Arakos
-
Hm - Fehlermeldung sagt mir leider nichts - vlt. weiss jemand anders Rat.
Hast du vlt einen falschen Projekttyp gewählt oder sowas in der Art?
-
Neuinstallation von MSVC 2010 hilft da.