C++ Fragen zu Programm das Dezimalzahlen in Binärzahlen umwandeln soll.

Laschadura

Cadet 1st Year
Registriert
März 2020
Beiträge
9
Hallo zusammen.
Ich muss im Rahmen einer Vorlesung ein kleines Programm zur Umwandlung von Dezimalzahlen in Binärzahlen schreiben.

Die Aufgabenstellung lautet wie folgt:

Task
Write a program that inputs a natural, i.e., unsigned int, number n and outputs the binary digits of n in the correct order (i.e., starting with the most significant bit). Do not output the leading zeros.

Restrictions: you cannot assume that int is 32 bits (ie. could be much smaller or much larger) and only the iostream standard library header is allowed. No arrays are permitted.

Important: The use of goto statements is prohibited.


Dazu habe ich das folgende Programm geschrieben:

C++:
#include<iostream>


int main()

{

  unsigned int n;


  std::cin >> n;


  if (n == 0)

  std::cout << "0";

  else

  {

    while (n != 0)

    {

      if ((n % 2) == 0)

      {

        std::cout << "0";

        n = n/2;

      }

      else

      std::cout << "1";

      n = n/2;

    }
  }

  return 0;

}

Das Problem ist, dass dieses Programm die Binärzahl umgekehrt ausgibt.

Also wenn die Zahl 11100 sein müsste, kommt 00111 raus.
Ich weiss nicht wie ich das ändern kann ohne die Bedingungen in der Aufgabenstellung zu verletzten. Kann mir hier jemand weiterhelfen?
 
Zuletzt bearbeitet:
Auf welcher CPU läßt Du dieses Programm laufen? Dann schau mal nach
Byte-Reihenfolge Litte Endian oder Big Endian, dann findest Du Deine Lösung. ;)
 
  • Gefällt mir
Reaktionen: Laschadura
Wieso nicht einfach die Bitfolge speichern, dann umdrehen, dann ausgeben?
 
das wäre meine Lösung ->


C:
unsigned char v_BitCnt_u8;
unsigned int    v_NCopy_ux;


if( n == 0u )
{
    std::cout << "0";
}
else
{
  v_NCopy_ux = n;                   /* n sichern */

  /* Anzahl von Bits scannen */
  for( v_BitCnt_u8 = 0u; v_NCopy_ux != 0; v_BitCnt_u8++ )
  {
    v_NCopy_ux >>= 1;              /* um 1 nach rechts shiften, oder durch 2 teilen */
  }

  /* n in BIN ausgeben */
  for( ; v_BitCnt_u8 != 0u; v_BitCnt_u8-- )
  {
    if( (n & (1<<(v_BitCnt_u8-1u)) != 0u )    /* ?? BIT gesetzt */
    {
      std::cout << "1";                          /* eine 1 ausgeben */
    }
    else                                                /* BIT nicht gesetzt */
    {
      std::cout << "0";                         /* eine 0 ausgeben */
    }
  }
}
 
Zuletzt bearbeitet:
Hallo,

hier eine einfache Rekursive Lösung:
C++:
void dez2bin(long dez)
{
    if(dez>0)
    {
        dez2bin(dez>>1);
        std::cout<<(dez%2);
    }
    return;
}

@Aliosy: Von embedded stand in der Fragestellung nichts. Vielen Dank für das Lob :daumen:.
@PHuV: Rekursive Algorithmen brauchen mehr Speicher (Heap Stack) für die Ausführung und der ist im embedded Bereich meistens sehr knapp.

Viele Grüße

Panzerfahrer
 
Zuletzt bearbeitet: (Korrigiert, nachdem ich die Code-Funktion gefunden habe. Danke @PHuV)
Leute, bitte nutzt doch die Code-Funktion
Code:
#include<iostream>

int main()

{

    printf("Datt is mein Code!\n");
    return 0;
}

vom Forum hier. Code als Klartext hier reinposten sieht nicht gut aus.

@Aliosy
Kannst Du mir das bitte mal als Nichtembedded-Entwickler erklären, wieso? :confused_alt:
 
  • Gefällt mir
Reaktionen: BAGZZlash und RalphS
Wie @PHuV sagt: bitte Codetags verwenden. Grad in der C Familie gibts genug Elemente, die die Forensoftware um Formatieren verwendet und ohne Codetags ist dann der Pointer kursiv und ohne * davor.

Gemäß Aufgabenstellung wäre mein Vorschlag, modulo seinzulassen und stattdessen nach bitshift zu schauen. Insbesondere geht bitshift nach links und auch nach rechts.

Protip: shift left/right hat unterschiedliche Bedeutungen, aber Programmierung ist nicht dasselbe wie Mathematik und hier geht es um die Darstellung. Der ausgegebene Wert muß nicht dem eingegebenen entsprechen. Er muß nur so aussehen — ein feiner, aber signifikanter Unterschied.
 
RalphS schrieb:
Gemäß Aufgabenstellung wäre mein Vorschlag, modulo seinzulassen und stattdessen nach bitshift zu schauen. Insbesondere geht bitshift nach links und auch nach rechts.
Für bitshift benötigst Du genauso wie bei der von mir verlinkten Lösung die bitset - library, was nach Aufgabenstellung nicht erlaubt ist.

Es handelt sich um eine Übungsaufgabe für die Nutzung von iostream. Der TE soll also den Umgang mit Streams üben ... es geht nicht wirklich um eine Lösung der Problematik.

/edit:
Vermutlich soll der TE lernen (bzw. üben), wie man einen Stream puffert, manipuliert und ausgibt. So würde ich zu mindestens den Sinn einer Übungsaufgabe mit der Einschränkung auf iostream sehen. Wenn der TE also auf ein Problem gestoßen ist, dass der Stream falsch herum ausgegeben wird, dann soll er ziemlich sicher dieses Problem auf Streamebene lösen. Vermutlich wurde das dafür notwendige Wissen in der Vorlesung vermittelt ...
 
Zuletzt bearbeitet:
... Eh? Für sowas dermaßen Grundlegendes braucht man eine Library? 16>>2 geht nicht ohne und 5<<3 auch nicht?

Kann das grad nicht testen... hab aber halb die Hoffnung, daß sowas auch nativ gehen sollte.

Gut möglich daß Du recht hast mit dem Anspruch - ich dachte eher an die Vermittlung von UmdieEckedenken, aber bin auch nicht der Prof.
 
Andreas_ schrieb:
Für bitshift benötigst Du genauso wie bei der von mir verlinkten Lösung die bitset - library
RalphS schrieb:
... Eh? Für sowas dermaßen Grundlegendes braucht man eine Library? 16>>2 geht nicht ohne und 5<<3 auch nicht?

Kann das grad nicht testen... hab aber halb die Hoffnung, daß sowas auch nativ gehen sollte.
Bitshifts in C und C++ sind Language-level Features und benötigen keine Library! Gleich wie alle anderen Operatoren auf Primitive-types.
In C++ braucht man nur dann eine Library wenn man überladene Operatoren haben will, wie zB operator<< für Streams.

Gruß
BlackMark
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Aliosy
Laschadura schrieb:
Hallo zusammen.
Ich muss im Rahmen einer Vorlesung ein kleines Programm zur Umwandlung von Dezimalzahlen in Binärzahlen schreiben.

Die Aufgabenstellung lautet wie folgt:

Task
Write a program that inputs a natural, i.e., unsigned int, number n and outputs the binary digits of n in the correct order (i.e., starting with the most significant bit). Do not output the leading zeros.

Restrictions: you cannot assume that int is 32 bits (ie. could be much smaller or much larger) and only the iostream standard library header is allowed. No arrays are permitted.

Important: The use of goto statements is prohibited.


Dazu habe ich das folgende Programm geschrieben:

C++:
#include<iostream>


int main()

{

  unsigned int n;


  std::cin >> n;


  if (n == 0)

  std::cout << "0";

  else

  {

    while (n != 0)

    {

      if ((n % 2) == 0)

      {

        std::cout << "0";

        n = n/2;

      }

      else

      std::cout << "1";

      n = n/2;

    }
  }

  return 0;

}

Das Problem ist, dass dieses Programm die Binärzahl umgekehrt ausgibt.

Also wenn die Zahl 11100 sein müsste, kommt 00111 raus.
Ich weiss nicht wie ich das ändern kann ohne die Bedingungen in der Aufgabenstellung zu verletzten. Kann mir hier jemand weiterhelfen?

Nenn mich jetzt Simplicissimus aber: stopf die Scheisse innen String und gib den per for Schleife von hinten aus?

Ey Leute man kanns auch echt kompliziert machen...

Edith: ich les grad 'no arrays are permitted', damit ist ein String ja auch raus facepalm
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: BAGZZlash
weitere Möglichkeit: Größe des int mit dem sizeof Operator bestimmen: Etwa so:

C++:
unsigned int n;
std::cin >> n;
bool leading_zero = true;
for (std::size_t  i = sizeof (unsigned int)*8 -1; i >= 0; i--) {
  unsigned int mask = 1<< i;
  if (( n & mask) == 0)
   if (! leading_zero)
    std::cout >> '0';
   else {
    leading_zero = false;
    std::cout >>'1';
   }
}
 
Zuletzt bearbeitet:
Einer meiner Kommilitonen hat mir folgende Lösung präsentiert:
C++:
#include<iostream>


int main()
{
  unsigned int n, rem;
  std::string bin;
 
  std::cin >> n;
 
  if (n == 0)
  std::cout << "0";
 
    while (n != 0)
    {
      rem = n % 2;
      n = n / 2;
      bin = std::to_string(rem) + bin;
    }
    
    std::cout << bin;
    
 
  return 0;
}

Aber ich dachte das ein String ein array ist? Langsam denke ich die haben ein Fehler in der Übungsstellung.
Danke für die vielen Antworten :)
 
  • Gefällt mir
Reaktionen: nerdalicious
Laschadura schrieb:
Aber ich dachte das ein String ein array ist? Langsam denke ich die haben ein Fehler in der Übungsstellung.
Danke für die vielen Antworten :)

Diese Lösung ist gut. Du könntest die Reste modulo 2 auch in einem Array speichern und zum Schluss in String konvertieren. Der Compiler wird übrigens Operationen / 2 und % 2 mit Bitshifts implementieren. Du kannst also guten Gewissens die Beiträge bezüglich Shifts ignorieren. Bedenke aber, dass der Compiler dies nur kann, wenn die Divisoren oder der Modus Zahlenliterale sind. Wenn der Divisor aus einer Variable kommt z.b. n / m, kann der Compiler dieser Optimierung nicht machen.

Alles in allem ist alles bis auf die String Konvertierung so schnell wie man es sich vorstellen kann. Angesichts, dass der Input begrenzt ist, kannst die Lösung deines Studienkollegen als Musterlösung betrachten.

Gruss
 
  • Gefällt mir
Reaktionen: Laschadura
Zurück
Oben