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.