¿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.


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

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

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)


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).


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

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.


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
}

¿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

Imprimir la cantidad incorrecta de bits. 111 000 110 son 9 bits, no 8.
David Ledger


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

-5

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

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

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;

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.