Wie drucke ich (mit cout) eine Zahl in binärer Form?

215

Ich absolviere einen College-Kurs über Betriebssysteme und wir lernen, wie man von binär zu hexadezimal, dezimal zu hexadezimal usw. konvertiert. Heute haben wir gerade gelernt, wie vorzeichenbehaftete / vorzeichenlose Zahlen unter Verwendung des Zweierkomplements (~ number) im Speicher gespeichert werden + 1).

Wir haben ein paar Übungen auf Papier zu machen und ich möchte meine Antworten überprüfen können, bevor ich meine Arbeit dem Lehrer vorlege. Ich habe ein C ++ - Programm für die ersten Übungen geschrieben, aber jetzt bin ich nicht sicher, wie ich meine Antwort mit dem folgenden Problem überprüfen kann:

char a, b;

short c;
a = -58;
c = -315;

b = a >> 3;

und wir müssen die binäre Darstellung zeigen , in dem Speicher von a, bund c.

Ich habe es auf Papier gemacht und es gibt mir die folgenden Ergebnisse (alle binären Darstellungen im Speicher der Zahlen nach dem Komplement der beiden):

a = 00111010 (es ist ein Zeichen, also 1 Byte)

b = 00001000 (es ist ein Zeichen, also 1 Byte)

c = 11111110 11000101 (es ist kurz, also 2 Bytes)

Gibt es eine Möglichkeit, meine Antwort zu überprüfen? Gibt es in C ++ eine Standardmethode, um die binäre Darstellung im Speicher einer Zahl anzuzeigen, oder muss ich jeden Schritt selbst codieren (das Komplement der beiden berechnen und dann in binär konvertieren)? Ich weiß, dass Letzteres nicht so lange dauern würde, aber ich bin gespannt, ob es einen Standardweg gibt.

Jesse Emond
quelle
2
Verstehst du die hexadezimale Darstellung? Wenn Sie dies tun, können Sie die Hex-Darstellung (mit dem std::hex) Manipulator drucken - ich überlasse es Ihnen als Übung, den Rest
Nim
3
Sie betonen viel "in Erinnerung", aber ich hoffe, sie bringen Sie nicht dazu, sich mit Endian-Problemen zu befassen.
Mark Ransom
Wissen Sie, was Endianness ist? Wenn ja, interessiert Sie diese Übung? Die Antwort auf diese Fragen kann die Antwort auf Ihre Frage beeinflussen.
R. Martinho Fernandes
Abhängig von Ihrer IDE können Sie den genauen Speicherinhalt von Visual Studio verwenden, wenn Sie nur die Richtigkeit Ihrer handgeschriebenen Lösung überprüfen und kein Programm schreiben möchten, um etwas Nützliches anzuzeigen.
Kiley Naro
1
Sogar Google tut dies, zum Beispiel "-58 in Binär" - aber +1, um herauszufinden, wie man es selbst im Code macht.
Konrad Rudolph

Antworten:

419

Der einfachste Weg ist wahrscheinlich, eine std::bitsetDarstellung des Werts zu erstellen und diese dann zu streamen cout.

#include <bitset>
...

char a = -58;    
std::bitset<8> x(a);
std::cout << x << '\n';

short c = -315;
std::bitset<16> y(c);
std::cout << y << '\n';
Jerry Sarg
quelle
23
Ah, ich vergesse immer wieder std::bitset! +1von mir.
sbi
2
Entschuldigen Sie meine Unwissenheit, aber zeigt dies nur die binäre Darstellung einer Zahl (z. B. 8 wäre 00001000) oder ihre Speicherdarstellung (z. B. wie -8 gespeichert würde, wenn Sie sich um das Vorzeichenbit kümmern und das "Zweierkomplement" verwenden)?
Jesse Emond
12
Das bitsetKonstruktorargument von @Jesse: wird als vorzeichenloser Wert interpretiert, der dem Zweierkomplement entspricht. Genau genommen garantiert C ++ keine Zweierkomplementarithmetik, und auch die -58 >> 3Operation in Ihrem Beispiel ist undefiniert.
Potatoswatter
Kann ich den Bitset-Wert (in diesem Beispiel x oder y) in ein Zeichen * umwandeln?
Nirvanaswap
1
Danke Jerry, ich habe to_string Minuten später entdeckt. Zu Ihrer Information, Casting funktioniert nicht, die Bitset-Variable ist ein Objekt einer wirklich arkan aussehenden Bitset3ul (?!) - Klasse. Am besten lassen Sie die Abstraktionen die Arbeit machen!
Nirvanaswap
102

Verwenden Sie die On-the-Fly-Konvertierung zu std::bitset. Keine temporären Variablen, keine Schleifen, keine Funktionen, keine Makros.

Live On Coliru

#include <iostream>
#include <bitset>

int main() {
    int a = -58, b = a>>3, c = -315;

    std::cout << "a = " << std::bitset<8>(a)  << std::endl;
    std::cout << "b = " << std::bitset<8>(b)  << std::endl;
    std::cout << "c = " << std::bitset<16>(c) << std::endl;
}

Drucke:

a = 11000110
b = 11111000
c = 1111111011000101
r233967
quelle
6
Beachten Sie, dass keine Hardcodierungsgröße erforderlich ist. ZB zum Drucken xverwenden : std::cout << std::bitset<8*sizeof(x)>(x).
Apollys unterstützt Monica
25

Wenn Sie die Bitdarstellung eines Objekts anzeigen möchten, nicht nur eine Ganzzahl, denken Sie daran, diese zuerst als Zeichenarray neu zu interpretieren. Anschließend können Sie den Inhalt dieses Arrays als Hex oder sogar als Binärdatei (über Bitset) drucken:

#include <iostream>
#include <bitset>
#include <climits>

template<typename T>
void show_binrep(const T& a)
{
    const char* beg = reinterpret_cast<const char*>(&a);
    const char* end = beg + sizeof(a);
    while(beg != end)
        std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
    std::cout << '\n';
}
int main()
{
    char a, b;
    short c;
    a = -58;
    c = -315;
    b = a >> 3;
    show_binrep(a);
    show_binrep(b);
    show_binrep(c);
    float f = 3.14;
    show_binrep(f);
}

Beachten Sie, dass die meisten gängigen Systeme sind Little-Endian, so dass der Ausgang show_binrep(c)ist nicht der 1111111 011000101 Sie erwarten, weil das nicht ist , wie es im Speicher gespeichert ist. Wenn Sie nach einer Wertedarstellung in Binärform suchen , cout << bitset<16>(c)funktioniert eine einfache .

Cubbi
quelle
11

Gibt es in C ++ eine Standardmethode, um die binäre Darstellung einer Zahl [...] im Speicher anzuzeigen?

Nein, es gibt kein std::bin, wie std::hexoder std::dec, aber es ist nicht schwer, selbst eine Binärzahl auszugeben:

Sie geben das Bit ganz links aus, indem Sie alle anderen maskieren, nach links verschieben und dies für alle vorhandenen Bits wiederholen.

(Die Anzahl der Bits in einem Typ beträgt sizeof(T) * CHAR_BIT.)

sbi
quelle
7

Ähnlich wie bereits veröffentlicht, nur Bitverschiebung und Maske verwenden, um das Bit zu erhalten. Als Vorlage verwendbar für jeden Typ ( nur nicht sicher, ob es einen Standardweg gibt, um die Anzahl der Bits in 1 Byte zu ermitteln, habe ich hier 8 verwendet ).

#include<iostream>
#include <climits>

template<typename T>
void printBin(const T& t){
    size_t nBytes=sizeof(T);
    char* rawPtr((char*)(&t));
    for(size_t byte=0; byte<nBytes; byte++){
        for(size_t bit=0; bit<CHAR_BIT; bit++){
            std::cout<<(((rawPtr[byte])>>bit)&1);
        }
    }
    std::cout<<std::endl;
};

int main(void){
    for(int i=0; i<50; i++){
        std::cout<<i<<": ";
        printBin(i);
    }
}
Eudoxos
quelle
3
Die Standardmethode zum Abrufen der Anzahl der Bits pro Byte ist das Makro CHAR_BIT.
R. Martinho Fernandes
Es scheint, dass sbi den Beitrag von Εύδοξος gemäß dem Kommentar von @ R.MartinhoFernandes bearbeitet hat. Den letzten Satz hat er jedoch nicht geändert. Ich werde bearbeiten.
Gsamaras
3

Wiederverwendbare Funktion:

template<typename T>
static std::string toBinaryString(const T& x)
{
    std::stringstream ss;
    ss << std::bitset<sizeof(T) * 8>(x);
    return ss.str();
}

Verwendung:

int main(){
  uint16_t x=8;
  std::cout << toBinaryString(x);
}

Dies funktioniert mit allen Arten von ganzen Zahlen.

Shital Shah
quelle
1
#include <iostream> 
#include <cmath>       // in order to use pow() function
using namespace std; 

string show_binary(unsigned int u, int num_of_bits);

int main() 
{ 

  cout << show_binary(128, 8) << endl;   // should print 10000000
  cout << show_binary(128, 5) << endl;   // should print 00000
  cout << show_binary(128, 10) << endl;  // should print 0010000000

  return 0; 
}

string show_binary(unsigned int u, int num_of_bits) 
{ 
  string a = "";

  int t = pow(2, num_of_bits);   // t is the max number that can be represented

  for(t; t>0; t = t/2)           // t iterates through powers of 2
      if(u >= t){                // check if u can be represented by current value of t
          u -= t;
          a += "1";               // if so, add a 1
      }
      else {
          a += "0";               // if not, add a 0
      }

  return a ;                     // returns string
}
Schreibe hier deinen Namen hin
quelle
Sollte es nicht sein int t = pow(2, num_of_bits - 1);?
BmyGuest
0

Mit der alten C ++ - Version können Sie dieses Snippet verwenden:

template<typename T>
string toBinary(const T& t)
{
  string s = "";
  int n = sizeof(T)*8;
  for(int i=n-1; i>=0; i--)
  {
    s += (t & (1 << i))?"1":"0";
  }
  return s;
}

int main()
{
  char a, b;

  short c;
  a = -58;
  c = -315;

  b = a >> 3;

  cout << "a = " << a << " => " << toBinary(a) << endl;
  cout << "b = " << b << " => " << toBinary(b) << endl;
  cout << "c = " << c << " => " << toBinary(c) << endl;
}

a = => 11000110
b = => 11111000
c = -315 => 1111111011000101
Ratah
quelle
Drucken der falschen Anzahl von Bits. 111 000 110 ist 9 Bit, nicht 8.
David Ledger
Ich habe einen
Grenzfehler
0

Verwenden der std :: bitset-Antworten und Convenience-Vorlagen:

#include <iostream>
#include <bitset>
#include <climits>

template<typename T>
struct BinaryForm {
    BinaryForm(const T& v) : _bs(v) {}
    const std::bitset<sizeof(T)*CHAR_BIT> _bs;
};

template<typename T>
inline std::ostream& operator<<(std::ostream& os, const BinaryForm<T> bf) {
    return os << bf._bs;
}

Verwenden Sie es so:

auto c = 'A';
std::cout << "c: " << c << " binary: " << BinaryForm{c} << std::endl;
unsigned x = 1234;
std::cout << "x: " << x << " binary: " << BinaryForm{x} << std::endl;
int64_t z { -1024 };
std::cout << "z: " <<  << " binary: " << BinaryForm{z} << std::endl;

Erzeugt Ausgabe:

c: A binary: 01000001
x: 1234 binary: 00000000000000000000010011010010
z: -1024 binary: 1111111111111111111111111111111111111111111111111111110000000000
user5673656
quelle
-5

Hier ist der wahre Weg, um eine binäre Darstellung einer Zahl zu erhalten:

unsigned int i = *(unsigned int*) &x;
user5463518
quelle
Nein ; Dies kopiert nur x in i. Es sei denn, Sie meinten das als Witz?
AnthonyD973
-11

Ist es das, wonach du suchst?

std::cout << std::hex << val << std::endl;
Kevin
quelle
30
Anmerkung des Moderators Ich habe versucht , antagonistische oder anderweitig nicht konstruktive Kommentare unter dieser Antwort selektiv zu löschen, und bin zu einem sehr unterbrochenen Gespräch gekommen. Alle Kommentare wurden gelöscht. Bitte halten Sie Kommentare professionell, konstruktiv und vor allem zum Thema. Wenn das OP dies entfernen wollte, hätte das OP es inzwischen entfernt. Wenn Sie mit dieser Antwort nicht einverstanden sind, stimmen Sie ab. Wenn Sie diese Antwort verbessern können, bearbeiten Sie sie. </argument>. Wirklich, wir sind Erwachsene, ja? Ich habe fast das Alter aller Kommentare überprüft, um sicherzustellen, dass alle über 13 Jahre alt waren.
Tim Post