¿Cómo imprimir (usando cout) un número en forma binaria?

216

Estoy siguiendo un curso universitario sobre sistemas operativos y estamos aprendiendo cómo convertir de binario a hexadecimal, decimal a hexadecimal, etc. y hoy aprendimos cómo los números con signo / sin signo se almacenan en la memoria usando el complemento de dos (~ número + 1).

Tenemos un par de ejercicios que hacer en papel y me gustaría poder verificar mis respuestas antes de presentar mi trabajo al maestro. Escribí un programa en C ++ para los primeros ejercicios, pero ahora no sé cómo puedo verificar mi respuesta con el siguiente problema:

char a, b;

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

b = a >> 3;

y necesitamos mostrar la representación binaria en memoria de a, by c.

Lo hice en papel y me da los siguientes resultados (todas las representaciones binarias en memoria de los números después del complemento de dos):

a = 00111010 (es un char, entonces 1 byte)

b = 00001000 (es un char, entonces 1 byte)

c = 11111110 11000101 (es un corto, entonces 2 bytes)

¿Hay alguna forma de verificar mi respuesta? ¿Hay una forma estándar en C ++ para mostrar la representación binaria en la memoria de un número, o tengo que codificar cada paso yo mismo (calcular el complemento de dos y luego convertirlo a binario)? Sé que esto último no llevaría tanto tiempo, pero tengo curiosidad por saber si hay una forma estándar de hacerlo.

Jesse Emond
fuente
2
¿Entiendes la representación hexadecimal? si lo hace, puede imprimir la representación hexadecimal (usando el std::hex) manipulador - Lo dejaré como un ejercicio para que pueda resolver el resto ...
Nim
3
Enfatizas mucho "en la memoria", pero espero que no te hagan lidiar con problemas endian.
Mark Ransom
¿Sabes que tienes alguna idea de lo que es endianness? Si lo hace, ¿le importa para este ejercicio? La respuesta a estas preguntas puede influir en la respuesta a su pregunta.
R. Martinho Fernandes
Dependiendo de su IDE, si solo está buscando verificar la corrección de su solución escrita a mano y no está escribiendo un programa para mostrar algo útil, puede usar algo como el visor de memoria de Visual Studio para ver el contenido exacto de la memoria.
Kiley Naro
1
Incluso Google hace esto, por ejemplo, "-58 en binario" , pero +1 por querer averiguar cómo hacerlo usted mismo en código.
Konrad Rudolph

Respuestas:

420

La forma más fácil es crear un std::bitsetvalor representativo y luego transmitirlo 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';
Jerry Coffin
fuente
23
Ah, me sigo olvidando std::bitset! +1de mi parte.
sbi
2
Disculpe mi ignorancia, pero ¿esto solo mostrará la representación binaria de un número (por ejemplo, 8 sería 00001000) o su representación en memoria (por ejemplo, ¿cómo se almacenaría -8 cuidando el bit de signo y usando el "complemento a dos")?
Jesse Emond
12
@Jesse: bitsetel argumento del constructor se interpreta como un valor sin signo, que funciona igual que el complemento de dos. Estrictamente hablando, C ++ no garantiza la aritmética del complemento a dos, y también la -58 >> 3operación en su ejemplo no está definida.
Potatoswatter
¿Puedo convertir el valor del conjunto de bits (es decir, x o y en este ejemplo) a un char *?
nirvanaswap
1
Gracias Jerry, descubrí to_string minutos después. Para su información, la conversión no funciona, la variable bitset es un objeto de una clase bitset3ul (?!) Realmente de aspecto arcano. ¡Lo mejor es dejar que las abstracciones hagan el trabajo!
nirvanaswap
102

Utilice la conversión sobre la marcha a std::bitset. Sin variables temporales, sin bucles, sin funciones, sin 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;
}

Huellas dactilares:

a = 11000110
b = 11111000
c = 1111111011000101
r233967
fuente
66
Tenga en cuenta que el tamaño de codificación rígida no es necesario. Por ejemplo, para imprimir xsu uso: std::cout << std::bitset<8*sizeof(x)>(x).
Apollys apoya a Monica el
25

Si desea mostrar la representación en bits de cualquier objeto, no solo un número entero, recuerde reinterpretar primero como una matriz de caracteres, luego puede imprimir el contenido de esa matriz, como hexadecimal o incluso como binario (a través de un conjunto de bits):

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

Tenga en cuenta que los sistemas más comunes son little-endian, por lo que el resultado noshow_binrep(c) es el 1111111 011000101 que espera, porque no es así como se almacena en la memoria. Si está buscando una representación de valor en binario, entonces un simple funciona.cout << bitset<16>(c)

Cubbi
fuente
11

¿Hay una forma estándar en C ++ para mostrar la representación binaria en la memoria de un número [...]?

No. No hay std::bin, like std::hexo std::dec, pero no es difícil generar un número binario usted mismo:

Sacas el bit que está más a la izquierda enmascarando a todos los demás, desplazas a la izquierda y repites eso para todos los bits que tienes.

(El número de bits en un tipo es sizeof(T) * CHAR_BIT).

sbi
fuente
7

Similar a lo que ya está publicado, solo usando bit-shift y máscara para obtener el bit; utilizable para cualquier tipo, siendo una plantilla ( solo que no estoy seguro si hay una forma estándar de obtener el número de bits en 1 byte, usé 8 aquí ).

#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
fuente
3
La forma estándar de obtener el número de bits por byte es la macro CHAR_BIT.
R. Martinho Fernandes
Parece que sbi editó la publicación de Εύδοξος según el comentario de @ R.MartinhoFernandes. Sin embargo, no cambió la última oración. Voy a editar
gsamaras
3

Función reutilizable:

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

Esto funciona con todo tipo de enteros.

Shital Shah
fuente
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
}
Escribe tu nombre aquí
fuente
¿No debería ser int t = pow(2, num_of_bits - 1);?
BmyGuest
0

Con la versión anterior de C ++, puede usar este fragmento:

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
fuente
Imprimir la cantidad incorrecta de bits. 111 000 110 son 9 bits, no 8.
David Ledger
Cometí un
0

Utilizando las respuestas std :: bitset y plantillas de conveniencia:

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

Usándolo así:

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 salida:

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

Aquí está la verdadera forma de obtener una representación binaria de un número:

unsigned int i = *(unsigned int*) &x;
usuario5463518
fuente
No ; esto solo copia x en i. ¿A menos que quisieras decir esto como una broma?
AnthonyD973
-11

¿Es esto lo que estás buscando?

std::cout << std::hex << val << std::endl;
Kevin
fuente
30
Moderador Nota I intentado para purgar los comentarios antagónicos o de otra manera no constructivas en virtud de esta respuesta selectiva, y que terminó con una conversación muy roto. Todos los comentarios fueron purgados. Por favor mantenga comentarios profesionales, constructivos y sobre todo sobre el tema Si el OP quisiera eliminar esto, el OP ya lo habría eliminado. Si no está de acuerdo con esta respuesta, vote. Si puede mejorar esta respuesta, edite. </argument>. En serio, somos adultos, ¿sí? Casi revisé las edades en todos los comentarios aquí para asegurarme de que todos tenían más de 13 años.
Tim Post