Come stampare (usando cout) un numero in forma binaria?


216

Sto seguendo un corso universitario sui sistemi operativi e stiamo imparando come convertire da binario a esadecimale, decimale in esadecimale, ecc. E oggi abbiamo appena appreso come i numeri firmati / non firmati sono memorizzati nella memoria usando il complemento a due (~ numero + 1).

Abbiamo un paio di esercizi da fare su carta e vorrei essere in grado di verificare le mie risposte prima di presentare il mio lavoro all'insegnante. Ho scritto un programma C ++ per i primi esercizi ma ora sono bloccato su come ho potuto verificare la mia risposta con il seguente problema:

char a, b;

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

b = a >> 3;

e dobbiamo mostrare la rappresentazione binaria in memoria di a, be c.

L'ho fatto su carta e mi dà i seguenti risultati (tutte le rappresentazioni binarie in memoria dei numeri dopo il complemento a due):

a = 00111010 (è un carattere, quindi 1 byte)

b = 00001000 (è un carattere, quindi 1 byte)

c = 11111110 11000101 (è breve, quindi 2 byte)

C'è un modo per verificare la mia risposta? Esiste un modo standard in C ++ per mostrare la rappresentazione binaria in memoria di un numero, o devo codificare ogni passo da solo (calcolare il complemento a due e poi convertire in binario)? So che quest'ultimo non richiederebbe così tanto tempo, ma sono curioso di sapere se esiste un modo standard per farlo.


2
capisci la rappresentazione esadecimale? se lo fai, puoi stampare il std::hexmanipolatore della rappresentazione esadecimale (usando il ) - Lascio che sia un esercizio per farti lavorare il resto ...
— Nim

3
Enfatizzi molto "in memoria", ma spero che non ti stiano facendo fronte alle questioni endiane.
— Mark Ransom,

Sai qualche idea su cosa sia l'endianità? Se lo fai, ti importa di questo esercizio? La risposta a queste domande può influenzare la risposta alla tua domanda.
— R. Martinho Fernandes,

A seconda del tuo IDE, se stai solo cercando di verificare la correttezza della tua soluzione scritta a mano e non stai effettivamente scrivendo un programma per visualizzare qualcosa di utile, potresti usare qualcosa come il visualizzatore di memoria di Visual Studio per visualizzare il contenuto esatto della memoria.
— Kiley Naro,

1
Anche Google lo fa, ad esempio "-58 in binario" , ma +1 per voler scoprire come farlo da soli nel codice.
— Konrad Rudolph,

Risposte:


420

Il modo più semplice è probabilmente quello di creare un std::bitsetvalore rappresentativo, quindi trasmetterlo a 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';

23
Ah, continuo a dimenticarmene std::bitset! +1da me.
— sbi,

2
Scusa la mia ignoranza, ma questo mostrerà solo la rappresentazione binaria di un numero (ad esempio 8 sarebbe 00001000) o la sua rappresentazione di memoria (ad esempio come -8 verrebbe memorizzato prendendosi cura del bit del segno e usando il "complemento a due")?
— Jesse Emond,

12
@Jesse: bitsetl'argomento del costruttore viene interpretato come un valore senza segno, che funziona allo stesso modo del complemento a due. A rigor di termini, C ++ non garantisce l'aritmetica del complemento di due, e anche l' -58 >> 3operazione nel tuo esempio non è definita.
— Potatoswatter,

Posso digitare il valore del bitset (es. Xey in questo esempio) su un carattere *?
— nirvanaswap,

1
Grazie Jerry, ho scoperto to_string pochi minuti dopo. Cordiali saluti, il casting non funziona, la variabile bitset è un oggetto di una classe bitset3ul (?!) Dall'aspetto davvero arcano. Meglio lasciare che le astrazioni facciano il lavoro!
— nirvanaswap,

102

Utilizza la conversione al volo in std::bitset. Nessuna variabile temporanea, nessun loop, nessuna funzione, nessuna macro.

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;
}

stampe:

a = 11000110
b = 11111000
c = 1111111011000101

6
Si noti che la dimensione del codice non è necessaria. Ad esempio, per stampare xuso: std::cout << std::bitset<8*sizeof(x)>(x).
— Apollys sostiene Monica

25

Se si desidera visualizzare la rappresentazione bit di qualsiasi oggetto, non solo un numero intero, ricordarsi di reinterpretare prima come array di caratteri, quindi è possibile stampare il contenuto di tale array, come esadecimale o persino come binario (tramite bitset):

#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);
}

Nota che i sistemi più comuni sono little-endian, quindi l'output di nonshow_binrep(c) è l'1111111 011000101 che ti aspetti, perché non è così che viene archiviato in memoria. Se stai cercando una rappresentazione di valore in binario, allora funziona semplicemente .cout << bitset<16>(c)


11

Esiste un modo standard in C ++ per mostrare la rappresentazione binaria in memoria di un numero [...]?

No. Non c'è std::bin, come std::hexo std::dec, ma non è difficile emettere un numero binario da soli:

Emetti il ​​bit più a sinistra mascherando tutti gli altri, spostando a sinistra e ripetendolo per tutti i bit che hai.

(Il numero di bit in un tipo è sizeof(T) * CHAR_BIT.)


7

Simile a ciò che è già stato pubblicato, basta usare bit-shift e maschera per ottenere il bit; utilizzabile per qualsiasi tipo, essendo un modello ( solo non sicuro se esiste un modo standard per ottenere il numero di bit in 1 byte, ho usato 8 qui ).

#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);
    }
}

3
Il modo standard per ottenere il numero di bit per byte è la macro CHAR_BIT.
— R. Martinho Fernandes,

Sembra che sbi abbia modificato il post di Εύδοξος secondo il commento di @ R.MartinhoFernandes. Tuttavia, non ha cambiato l'ultima frase. Lo modificherò.
— gsamaras,

3

Funzione riutilizzabile:

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

Uso:

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

Funziona con tutti i tipi di numeri interi.


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
}

Non dovrebbe essere int t = pow(2, num_of_bits - 1);?
— BmyGuest,

0

Utilizzando la vecchia versione C ++, puoi utilizzare questo frammento:

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

Stampa di un numero errato di bit. 111000 110 è 9 bit, non 8.
— David Ledger,

Ho fatto un errore al limite, per favore controlla ora
— Ratah,

0

Utilizzando le risposte std :: bitset e i modelli di convenienza:

#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;
}

Usandolo in questo modo:

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;

Genera output:

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

-5

Ecco il vero modo per ottenere la rappresentazione binaria di un numero:

unsigned int i = *(unsigned int*) &x;

No ; questo copia solo x in i. A meno che non lo intendessi come uno scherzo?
— AnthonyD973

-11

È questo quello che stai cercando?

std::cout << std::hex << val << std::endl;

30
Nota del moderatore Ho provato a eliminare selettivamente i commenti antagonisti o altrimenti non costruttivi sotto questa risposta, e ho finito con una conversazione molto interrotta. Tutti i commenti sono stati eliminati. Si prega di mantenere i commenti professionali, costruttivi e soprattutto sull'argomento. Se l'OP volesse rimuoverlo, l'OP lo avrebbe rimosso ormai. Se non sei d'accordo con questa risposta, allora vota. Se riesci a migliorare questa risposta, modifica. </argument>. Davvero, siamo adulti, sì? Ho quasi controllato l'età di tutto ciò che ha commentato qui per assicurarmi che tutti avessero più di 13 anni.
— Tim Post
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.