Forum: Mikrocontroller und Digitale Elektronik Binärzahlen berechnen in C


von Taw U. (tawo20)


Angehängte Dateien:

Lesenswert?

moin, ich wollte ein Programm schreiben was eine eingegebene Zahl in 
eine 8 bit Dualzahl umwandelt verstehe aber grad nicht wie ich die 
Rechnung codieren soll in C und ebenfalls wie ich die Ausgabe umgekehrt 
mache ?

Brauche Tipps bzw. Hilfe bei der Berechnung von binärzahlen in C !
Wie kann ich das mit den simplesten Befehlen machen ?

: Bearbeitet durch User
von Ben S. (bensch123)


Lesenswert?

1
uint8_t var = 0x4b;
2
3
for(uint8_t i = 8; i-- > 0;){
4
  if(var & (1<<i) std::cout << "1";
5
  else std::cout << "0";
6
}

von Theor (Gast)


Lesenswert?

Verstehst Du denn, wie die Umrechung funktioniert? Könntest Du eine 
beliebige ganze Dezimalzahl in das Binärsystem umrechnen?

von Taw U. (tawo20)


Lesenswert?

ja

von MaWin (Gast)


Lesenswert?

Taw U. schrieb:
> Brauche Tipps bzw. Hilfe bei der Berechnung von binärzahlen in C !

Du brauchst Tipps zum grundlegenden Programmieten.

drehrn geht einerseits durch Rekursion, eine Funktion die sich selbst 
aufrift
1
void putx(unsigned int x)
2
{
3
  if(x>1) putx(x/2);
4
  putc('0'+(x&1));
5
}
oder andererseits durch einen Pufferspeicher
1
char puffer[100];
2
int pos=100;
3
puffer[--pos]='\0';
4
do
5
{
6
  puffer[--pos]='0'+(x&1);
7
  x/=2;
8
}
9
while(x>0);
10
puts(puffer+pos);
oder man dreht gar nicht um sonder produziert gleich richtig
1
unsigned int bit=0x8000;
2
while(bit>x) bit>>=1;
3
while(bit)
4
{
5
  putc('0'+(x&bit?1:0));
6
  bit>>=1;
7
}

von Taw U. (tawo20)


Lesenswert?

Ben S. schrieb:
>
1
> uint8_t var = 0x4b;
2
> 
3
> for(uint8_t i = 8; i-- > 0;){
4
>   if(var & (1<<i) std::cout << "1";
5
>   else std::cout << "0";
6
> }
7
>

was heißt denn hier diese uint8_t, diese var oder auch cout<<0
also jetzt bin ich noch mehr durcheinander :)

von Theor (Gast)


Lesenswert?

Taw U. schrieb:
> ja

Hm. Hätte wohl dazu schreiben sollen, dass Du das mal mit eigenen Worten 
erklärst.
Daraus hättest Du dann erstmal in Stichworten, aber noch in normaler 
Sprache eine "Anweisung" schreiben können, als wenn jemand anders das 
Schritt für Schritt tun soll.
Das wäre so meine Idee: Dir nicht direkt das Programm hinzuschreiben, 
sondern mit Dir das Programm zu entwickeln.

von Einer K. (Gast)


Lesenswert?

Taw U. schrieb:
> was heißt denn hier diese uint8_t,
Das ist ein ganz üblicher  C Datentype.
Der wird in jedem C/Cpp Buch beschrieben.
Auch Google findet da sicherlich was.

Taw U. schrieb:
> diese var
Ein Benutzerdefinierter Variablenbezeicher.

Taw U. schrieb:
> auch cout<<0
Die C++ übliche Art und Weise Ausgaben zu tätigen.

von Taw U. (tawo20)


Lesenswert?

Arduino Fanboy D. schrieb:
> Taw U. schrieb:
>> was heißt denn hier diese uint8_t,
> Das ist ein ganz üblicher  C Datentype.
> Der wird in jedem C/Cpp Buch beschrieben.
> Auch Google findet da sicherlich was.
>
> Taw U. schrieb:
>> diese var
> Ein Benutzerdefinierter Variablenbezeicher.
>
> Taw U. schrieb:
>> auch cout<<0
> Die C++ übliche Art und Weise Ausgaben zu tätigen.

mit c++ hab ich noch nicht angefangen gibt es keine Variante wo man nur 
c benutzt?

von HildeK (Gast)


Lesenswert?

Taw U. schrieb:
> was heißt denn hier diese uint8_t, diese var oder auch cout<<0
> also jetzt bin ich noch mehr durcheinander :)

uint8_t ist eine Deklaration für eine Variable mit 8 Bit ohne 
Vorzeichen, vergleichbar mit unsigned char. Steht für unsigned int mit 8 
Bit.
Ich habe es mal für einen Anfänger etwas umgeschrieben, ohne C++ 
statements und mit einem Variablenname, der für Ungeübte zu weniger 
Verwirrung führt.
1
  uint8_t zahl = 42; // war oben der Name 'var' ...
2
  uint8_t i, ergebnis; 
3
4
  for (i=8; i>0; i--)
5
  {
6
     if ((zahl & (1<<i)) != 0) ergebnis = 1;
7
     else ergebnis = 0; 
8
     // "print ergebnis"  // Ausgabe welcher Art auch immer, MSB first, es
9
                          // werden nacheinander die Stellen von MSB 
10
                          // nach LSB genannt.
11
  }

von Ben S. (bensch123)


Lesenswert?

HildeK schrieb:
> Ich habe es mal für einen Anfänger etwas umgeschrieben,

Deine Schleife zählt von 8 bis 1 und nicht von 7 bis 0.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

HildeK schrieb:
> Ich habe es mal für einen Anfänger etwas umgeschrieben
Leider ist dieses Beispiel zwar vollkommen korrekt, aber jetzt nicht 
das, was das Bild oben vorgaukelt.
Natürlich könnte man sagen, dass diese Shifts ja quasi genau diese 
Divisionen sind, aber formal "korrekt" müsste es so aussehen:
1
  for (i=0; i<8; i++)
2
  {
3
     if ( zahl != ((zahl/2)*2) ) // wenn bei der Division ein Rest auftreten wird
4
          ergebnis = 1;          // --> Rest = 1
5
     else ergebnis = 0;          // --> kein Rest
6
     zahl = zahl/2;              // für nächste Selle vorbereiten
7
     // "print ergebnis"  // Ausgabe welcher Art auch immer, LSB first, es
8
                          // werden nacheinander die Stellen von LSB 
9
                          // nach MSB genannt.
10
  }
Dabei muss man natürlich beachten, dass "zahl" ein ganzzahliger Wert 
ist, bei dessen Division der Rest abgeschnitten wird:
:
:
11/2 = 5
12/2 = 6
13/2 = 6
14/2 = 7
15/2 = 7
16/2 = 8
:
:
Mit ein wenig Nachdenken findet man dann den Trick von ((zahl/2)*2) 
leicht heraus.

von Taw U. (tawo20)


Lesenswert?

Lothar M. schrieb:
> HildeK schrieb:
>> Ich habe es mal für einen Anfänger etwas umgeschrieben
> Leider ist dieses Beispiel zwar vollkommen korrekt, aber jetzt nicht
> das, was das Bild oben vorgaukelt.
> Natürlich könnte man sagen, dass diese Shifts ja quasi genau diese
> Divisionen sind, aber formal "korrekt" müsste es so aussehen:
>
1
>   for (i=0; i<8; i++)
2
>   {
3
>      if ( zahl != ((zahl/2)*2) ) // wenn bei der Division ein Rest 
4
> auftreten wird
5
>           ergebnis = 1;          // --> Rest = 1
6
>      else ergebnis = 0;          // --> kein Rest
7
>      zahl = zahl/2;              // für nächste Selle vorbereiten
8
>      // "print ergebnis"  // Ausgabe welcher Art auch immer, LSB first, 
9
> es
10
>                           // werden nacheinander die Stellen von LSB
11
>                           // nach MSB genannt.
12
>   }
13
>
> Dabei muss man natürlich beachten, dass "zahl" ein ganzzahliger Wert
> ist, bei dessen Division der Rest abgeschnitten wird:
> :
> :
> 11/2 = 5
> 12/2 = 6
> 13/2 = 6
> 14/2 = 7
> 15/2 = 7
> 16/2 = 8
> :
> :
> Mit ein wenig Nachdenken findet man dann den Trick von ((zahl/2)*2)
> leicht heraus.

Was mach ich den jetzt noch falsch warum wird mir die BInärzahl nicht 
nicht ausgegeben. Bin grad komplett lost, sorry

#include <stdio.h>

int main(){
    int zahl;
    float i;
    float ergebnis;

    printf("\nGeben Sie bitte eine ganze Zahl ein: ");
    scanf("%i", &zahl);


     for (i=0; i<8; i++)
  {
     if ( zahl != ((zahl/2)*2) ) // wenn bei der Division ein Rest 
auftreten wird
          ergebnis = 1;          // --> Rest = 1
     else ergebnis = 0;          // --> kein Rest
     zahl = zahl/2;
    }
    printf("Die Binärzahl lautet:", ergebnis);

}

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Taw U. schrieb:
> Was mach ich den jetzt noch falsch warum wird mir die BInärzahl nicht
> nicht ausgegeben.

bitte lerne, deine "interaktion" mit dem mitlesenden Publikum zu 
präzisieren.

"Binärzahl wird nicht ausgegeben": Das ist zu wenig Information!

beschreibe:
Was war deine Eingabe?
was hättest du erwartet als Ausgabe?
Was wird statt dessen ausgegeben?

von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

Taw U. schrieb:
> was heißt denn hier diese uint8_t, diese var oder auch cout<<0
> also jetzt bin ich noch mehr durcheinander :)

cout ist ein C++ Kommando - damit brauchst Du Dir den Rest gar nicht 
mehr anzuschauen, weil der TO eine Binärzahlberechnung in C und nicht in 
C++ haben möchte.

von viele Wege führen nach Rom (Gast)


Lesenswert?

die Frage ist halt wie du diese Binärzahl darstellen willst. Als String?

Wenn die Zahl nicht "riesig" ist, dann kann man sie auch als eine Zahl 
abspeichern.

Man berechnet den Rest (wie auf der Skizze) und addiert diese Zahlen auf 
(aber gewichtet). Dadurch wird die Zahl gedreht (wie auf der Skizze).
1
#include <stdio.h>
2
3
long long
4
dec_to_bin (int dec)
5
{
6
   long long bin = 0;
7
8
   long long factor = 1;
9
10
   while (dec) {
11
      bin += (dec % 2) * factor;
12
      dec /= 2;
13
14
      factor *= 10;
15
   }
16
17
   return bin;
18
}
19
20
int
21
main (void)
22
{
23
   for (int x = 0; x < 20; x++)
24
      printf ("dec:\t%d \t bin:\t%lld\n",
25
              x,
26
              dec_to_bin (x));
27
   return 0;
28
}

von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

Taw U. schrieb:
> #include <stdio.h>
>
> int main(){
>     int zahl;
>     float i;
>     float ergebnis;
>
>     printf("\nGeben Sie bitte eine ganze Zahl ein: ");
>     scanf("%i", &zahl);
>
>      for (i=0; i<8; i++)
>   {
>      if ( zahl != ((zahl/2)*2) ) // wenn bei der Division ein Rest
> auftreten wird
>           ergebnis = 1;          // --> Rest = 1
>      else ergebnis = 0;          // --> kein Rest
>      zahl = zahl/2;
>     }
>     printf("Die Binärzahl lautet:", ergebnis);
>
> }

Du setzt hier u.a. den Zählindex i als float an ... das ist schon mal 
falsch.
Ich würde mit switch ... case Statement arbeiten anstatt mit if ... then 
...else - Geschmackssache.
Auch in C gibt es einen Modulo-Operator, jedoch nur für Typ Integer:
https://manderc.com/operators/modoperator/index.php
Diesen Operator könntest Du aber dennoch für die Berechnung verwenden.
Sorry, das Programm ist nicht mein Problem, es gibt viele Wege zum Ziel
- deshalb werde ich es auch nicht lösen.

von Erwin D. (Gast)


Lesenswert?

Robert K. schrieb:
> Taw U. schrieb:
>> was heißt denn hier diese uint8_t, diese var oder auch cout<<0
>> also jetzt bin ich noch mehr durcheinander :)
>
> cout ist ein C++ Kommando - damit brauchst Du Dir den Rest gar nicht
> mehr anzuschauen, weil der TO eine Binärzahlberechnung in C und nicht in
> C++ haben möchte.

Er hat doch schon lange ein Beispiel in c bekommen...

von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

Taw U. schrieb:
> Brauche Tipps bzw. Hilfe bei der Berechnung von binärzahlen in C !
> Wie kann ich das mit den simplesten Befehlen machen ?

eigentlich ist Dein Problem mehr als albern bzw. offenbar will hier 
jeder Poster das Rad neu erfinden? Kann das sein?
Einmal Suchmaschine anwerfen ergibt schon die Lösung:
https://www.javatpoint.com/c-program-to-convert-decimal-to-binary

Sorry Leute, aber das Forum wird immer mehr zum Armutszeugnis ):

von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

Erwin D. schrieb:
> Er hat doch schon lange ein Beispiel in c bekommen...

richtig, und die Lösung bekam er jetzt von mir! ... und ich habe mich 
noch nicht mal bemüht :(

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Taw U. schrieb:
> Was mach ich den jetzt noch falsch warum wird mir die BInärzahl nicht
> nicht ausgegeben. Bin grad komplett lost, sorry

 ergebnis wird immer wieder überschrieben und nirgendwo ausgegeben.
1
     for (i=0; i<8; i++)
2
  {
3
     if ( zahl != ((zahl/2)*2) ) // wenn bei der Division ein Rest 
4
auftreten wird
5
          ergebnis = 1;          // --> Rest = 1
6
     else ergebnis = 0;          // --> kein Rest
7
     zahl = zahl/2;
8
    }
9
    printf("Die Binärzahl lautet:", ergebnis);

von Robert K. (Firma: Zombieland) (rko)


Lesenswert?

PS:
bei dem Fertigprogramm meines Links fehlt noch eine abschließende 
Klammer } im Quellcode.
Wenn man die gesetzt hat, funktioniert das Programm ... viel Spaß damit 
:-)

von HildeK (Gast)


Lesenswert?

Ben S. schrieb:
> Deine Schleife zählt von 8 bis 1 und nicht von 7 bis 0.

Ja, leider. 🙄

von Peter D. (peda)


Lesenswert?

Noch ne Variante:
1
void binout(uint8_t val)
2
{
3
  for (uint8_t mask = 0x80; mask; mask >>= 1)
4
    putchar( mask & val ? '1' : '0' );
5
}

von malsehen (Gast)


Lesenswert?

So nett?
Zum Freitag?
Hausaufgaben?

von M. K. (sylaina)


Lesenswert?

Peter D. schrieb:
> Noch ne Variante:
>
1
> void binout(uint8_t val)
2
> {
3
>   for (uint8_t mask = 0x80; mask; mask >>= 1)
4
>     putchar( mask & val ? '1' : '0' );
5
> }
6
>

Aus welchem Buch hast du's geklaut? Bei mir ists ein Data Becker 
Progmmierbuch aus den 90ern :D

von Peter D. (peda)


Lesenswert?

M. K. schrieb:
> Aus welchem Buch hast du's geklaut?

Ich habs einfach so hingeschrieben.
Zuerst hatte ich:
1
for (uint8_t mask = 0x80; mask; mask >>= 1)
2
  putchar( !!(mask & val) + '0' );
Das !! ist so eine Funktion, die man nicht mehr aus dem Kopf kriegt, 
wenn man sie einmal gesehen hat. Sie wirkt auf den ersten Blick nutzlos, 
danach aber sehr elegant.

von Stefan F. (Gast)


Lesenswert?

Peter D. schrieb:
> Das !! ist so eine Funktion

! ist die Negierung eine boolschen Ausdrucks.
!! ist die doppelte Negierung. Hier will man den Seiteneffekt nutzen, 
dass alle Zahlen ungleich 0 zu 1 werden.

von HildeK (Gast)


Lesenswert?

Peter D. schrieb:
> Ich habs einfach so hingeschrieben.

Ich weiß ja, dass du immer hocheffiziente Schreibweisen auf Lager hast. 
Aber da der TO bereits Verständnisprobleme beim 'uint8_t' und den 
Variablennamen 'var' nicht als solchen erkannt hatte, wird ihm das 
sicher nicht weiterhelfen.
Ich profitiere schon gelegentlich von deinen Codeschnipsel ...

von W.S. (Gast)


Lesenswert?

Taw U. schrieb:
> moin, ich wollte ein Programm schreiben was eine eingegebene Zahl in
> eine 8 bit Dualzahl umwandelt verstehe aber grad nicht wie ich die
> Rechnung codieren soll in C und ebenfalls wie ich die Ausgabe umgekehrt
> mache ?
>
> Brauche Tipps bzw. Hilfe bei der Berechnung von binärzahlen in C !

Nein, du brauchst keinerlei Tipps in C, sondern du brauchst etwas an 
eigenem Nachdenken über Herangehensweisen, Algorithmen und die 
Darstellung von Zahlen. das ist es, was du brauchst.

1. Die Zahlen als solche, also hier mal positiv definite ganze Zahlen. 
also von 0 über 1, 2, 3, ... bis fast unendlich. Konkret bis zu der 
Grenze, die durch deine rechnerinterne Darstellung gegben ist. In ein 
Byte passen da Zahlen 0..255 hinein, in ein int dann dasselbe mal 256 
und so weiter.

2. Negative Zahlen: das Zweierkomplement. Wiel muß eine Zahl in einem 
CPU-Register aussehen, damit beim Addieren von 1 eine 0 herauskommt? --> 
Selbststudium.

3. Menschlich lesbare Zahlen: Das sind aus Sicht des Rechners gar keine 
Zahlen, sondern Text. Also 1 oder mehrere Textzeichen gelle? Um die 
dem Rechner verständlich zu machen, muß man sie konvertieren.
(ich benutze hier mal ne hypothetische Programmiersprache)
 Fall a: Dezimalzahlen:
 while Textzeichen not in ('0'..'9') do hole nächstes Zeichen
 Ergebnis = 0
 while Textzeichen in ('0'..'9') do
  { Ergebnis = (Ergebnis * 10) + (Textzeichen - '0');
    hole nächstes Zeichen }

 Fall b: Hexadezimale Zahlen:
 derselbe Algorithmus, aber zusätzlich noch das Berücksichtigen von 
'A'..'F' bzw. 'a'..'f'
 und die Multiplikation nicht mit 10, sondern mit 16

 Fall c: Binärzahlen: derselbe Algorithms wie a: aber nur Zeichen 
'0'..'1' zu berücksuchtigen. Multiplikation mit 2, was man technisch 
auch durch einfache Linksverschiebung machen kann.

So. Das war's Prinzip für Eingabe-Konvertierungen.

Ausgabekonvertierungen:
Da gibt's 2 Herangehensweisen, die für unterschiedliche Hardware 
verschieden effektiv sind.
a) Abzählen. Das geht wie das schriftliche Dividieren, was du ja in der 
Schule gelernt hast. Für das Byte also
 Ziffer = '0'
 while Zahl >0 {Zahl = Zahl - 100); increment Ziffer; }
 Zahl = Zahl + 100; // rückstellen
 Ziffer ausgeben
 Ziffer = '0';
 while Zahl >0 {Zahl = Zahl - 10); increment Ziffer; }
 Zahl = Zahl + 10; // rückstellen
 Ziffer ausgeben
 Ziffer = Zahl + '0';
 Ziffer ausgeben

b) Division mit Rest, was bei den üblichen Arithmetik-Laufzeitroutinen 
als Funktion dabei ist. Also solange durch 10 teilen, bis Variable Null 
ist und jeweils den Divisionsrest als Ziffer hernehmen.

Also lerne zuerst mal die Herangehensweisen. Das Hinschreiben in irgend 
einer Programmiersprache ist nachrangig.

W.S.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.