Como imprimir (usando cout) um número em formato binário?

215

Estou seguindo um curso universitário sobre sistemas operacionais e estamos aprendendo a converter de binário em hexadecimal, decimal em hexadecimal, etc. + 1)

Temos alguns exercícios para fazer no papel e eu gostaria de poder verificar minhas respostas antes de enviar meu trabalho ao professor. Eu escrevi um programa C ++ para os primeiros exercícios, mas agora estou empolgado com a forma de verificar minha resposta com o seguinte problema:

char a, b;

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

b = a >> 3;

e precisamos mostrar a representação binária na memória de a, be c.

Eu fiz isso no papel e me fornece os seguintes resultados (todas as representações binárias na memória dos números após o complemento dos dois):

a = 00111010 (é um caractere, então 1 byte)

b = 00001000 (é um caractere, então 1 byte)

c = 11111110 11000101 (é curto, portanto, 2 bytes)

Existe uma maneira de verificar minha resposta? Existe uma maneira padrão em C ++ para mostrar a representação binária na memória de um número ou eu mesmo tenho que codificar cada etapa (calcular o complemento de dois e depois converter em binário)? Eu sei que o último não demoraria tanto, mas estou curioso para saber se existe uma maneira padrão de fazê-lo.

Jesse Emond
fonte
2
você entende representação hexadecimal? se o fizer, você pode imprimir a representação hexadecimal (usando o std::hex) manipulador - Vou deixar isso como um exercício para você trabalhar fora o resto ...
Nim
3
Você enfatiza "na memória" muito, mas espero que eles não estejam fazendo você lidar com questões endian.
Mark Ransom
Você tem alguma idéia sobre o que é endianness? Se sim, você se importa com esse exercício? A resposta a estas perguntas pode influenciar a resposta à sua pergunta.
R. Martinho Fernandes
Dependendo do seu IDE, se você apenas procura verificar a correção da sua solução escrita à mão e não está realmente escrevendo um programa para exibir algo útil, pode usar algo como o visualizador de memória do Visual Studio para exibir o conteúdo exato da memória.
Kiley Naro #
1
Até o Google faz isso, por exemplo, “-58 em binário” - mas +1 por querer descobrir como fazer isso sozinho no código.
Konrad Rudolph

Respostas:

419

A maneira mais fácil é provavelmente criar uma std::bitsetrepresentação do valor e transmitir isso para 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 Coffin
fonte
23
Ah, eu continuo esquecendo std::bitset! +1de mim.
SBI
2
Desculpe minha ignorância, mas isso mostrará apenas a representação binária de um número (por exemplo, 8 seria 00001000) ou sua representação em memória (por exemplo, como -8 seria armazenado cuidando do bit do sinal e usando o "complemento de dois")?
precisa saber é o seguinte
12
@ Jesse: bitseto argumento construtor é interpretado como um valor não assinado, que funciona da mesma forma que o complemento de dois. A rigor, o C ++ não garante a aritmética do complemento de dois e também a -58 >> 3operação no seu exemplo é indefinida.
Potatoswatter
Posso converter o valor do conjunto de bits (por exemplo, x ou y neste exemplo) em um caractere *?
Nirvanaswap
1
Obrigado Jerry, eu descobri to_string minutos depois. Para sua informação, a conversão não funciona, a variável bitset é um objeto de alguma classe bitset3ul (?!) Realmente de aparência misteriosa. Melhor deixar que as abstrações façam o trabalho!
Nirvanaswap
102

Use a conversão on-the-fly para std::bitset. Sem variáveis ​​temporárias, sem loops, sem funções, sem macros.

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

Impressões:

a = 11000110
b = 11111000
c = 1111111011000101
r233967
fonte
6
Observe que o tamanho da codificação não é necessário. Por exemplo, para imprimir xuso: std::cout << std::bitset<8*sizeof(x)>(x).
Apollys suporta Monica
25

Se você deseja exibir a representação de bits de qualquer objeto, não apenas um número inteiro, lembre-se de reinterpretar como uma matriz de caracteres primeiro, então você pode imprimir o conteúdo dessa matriz, como hexadecimal ou mesmo como binário (via 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);
}

Observe que os sistemas mais comuns são little-endian; portanto, a saída de nãoshow_binrep(c) é a 1111111 011000101 que você espera, porque não é assim que é armazenada na memória. Se você está procurando representação de valor em binário, um simples trabalho.cout << bitset<16>(c)

Cubbi
fonte
11

Existe uma maneira padrão em C ++ para mostrar a representação binária na memória de um número [...]?

Não. Não há std::bin, como std::hexoustd::dec , mas não é difícil gerar um número binário:

Você produz o bit mais à esquerda mascarando todos os outros, desloca para a esquerda e repete isso para todos os bits que você possui.

(O número de bits em um tipo é sizeof(T) * CHAR_BIT.)

sbi
fonte
7

Semelhante ao que já foi publicado, basta usar deslocamento e máscara de bits para obter o bit; utilizável para qualquer tipo, sendo um modelo ( só não tenho certeza se existe uma maneira padrão de obter o número de bits em 1 byte, usei 8 aqui ).

#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
fonte
3
A maneira padrão de obter o número de bits por byte é a macro CHAR_BIT.
R. Martinho Fernandes
Parece que o sbi editou o post de Εύδοξος de acordo com o comentário de @ R.MartinhoFernandes. No entanto, ele não mudou a última frase. Eu vou editar.
gsamaras
3

Função reutilizável:

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

Isso funciona com todos os tipos de números inteiros.

Shital Shah
fonte
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
}
Escreva seu nome aqui
fonte
Não deveria ser int t = pow(2, num_of_bits - 1);?
BmyGuest
0

Usando a versão antiga do C ++, você pode usar este trecho:

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
fonte
Imprimindo o número errado de bits. 111 000 110 é 9 bits, não 8.
David Ledger
Fiz erro limite, por favor, verifique agora
Ratah
0

Usando as respostas std :: bitset e os modelos de conveniência:

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

Usando assim:

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;

Gera saída:

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

Aqui está a verdadeira maneira de obter uma representação binária de um número:

unsigned int i = *(unsigned int*) &x;
user5463518
fonte
Não ; isso apenas copia x para i. A menos que você quis dizer isso como uma piada?
AnthonyD973
-11

É isso que você está procurando?

std::cout << std::hex << val << std::endl;
Kevin
fonte
30
Moderador Nota I tentou purgar comentários construtivos antagônicas ou de outra forma não sob esta resposta seletivamente, e acabei com uma conversa muito quebrado. Todos os comentários foram eliminados. Por favor, mantenha os comentários profissionais, construtivos e, acima de tudo, sobre o tópico. Se o OP quisesse remover isso, ele já o teria removido. Se você não concordar com esta resposta, vote. Se você pode melhorar esta resposta, edite. </argument>. Realmente, somos adultos, sim? Eu quase verificou as idades sobre tudo o que comentou aqui para garantir que todos foi mais de 13.
Tim Publicar