Comment imprimer (en utilisant cout) un nombre sous forme binaire?

216

Je suis un cours universitaire sur les systèmes d'exploitation et nous apprenons à convertir du binaire en hexadécimal, décimal en hexadécimal, etc. et aujourd'hui, nous venons d'apprendre comment les nombres signés / non signés sont stockés en mémoire en utilisant le complément à deux (~ nombre + 1).

Nous avons quelques exercices à faire sur papier et j'aimerais pouvoir vérifier mes réponses avant de soumettre mon travail à l'enseignant. J'ai écrit un programme C ++ pour les premiers exercices mais maintenant je suis bloqué sur la façon dont je pourrais vérifier ma réponse avec le problème suivant:

char a, b;

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

b = a >> 3;

et nous devons montrer la représentation binaire en mémoire de a, bet c.

Je l'ai fait sur papier et cela me donne les résultats suivants (toutes les représentations binaires en mémoire des nombres après le complément à deux):

a = 00111010 (c'est un caractère, donc 1 octet)

b = 00001000 (c'est un caractère, donc 1 octet)

c = 11111110 11000101 (c'est un court, donc 2 octets)

Existe-t-il un moyen de vérifier ma réponse? Existe-t-il un moyen standard en C ++ d'afficher la représentation binaire en mémoire d'un nombre, ou dois-je coder chaque étape moi-même (calculer le complément à deux puis convertir en binaire)? Je sais que ce dernier ne prendrait pas autant de temps, mais je suis curieux de savoir s'il existe un moyen standard de le faire.

Jesse Emond
la source
2
comprenez-vous la représentation hexadécimale? si vous le faites, vous pouvez imprimer la représentation hexadécimale (en utilisant le std::hex) manipulateur - je vais le laisser comme un exercice pour que vous puissiez résoudre le reste ...
Nim
3
Vous insistez beaucoup sur «en mémoire», mais j'espère qu'ils ne vous obligent pas à résoudre les problèmes endiens.
Mark Ransom
Savez-vous avoir une idée de ce qu'est l'endianité? Si vous le faites, vous en souciez-vous pour cet exercice? La réponse à ces questions peut influencer la réponse à votre question.
R. Martinho Fernandes
Selon votre IDE, si vous cherchez simplement à vérifier l'exactitude de votre solution manuscrite et que vous n'écrivez pas réellement un programme pour afficher quelque chose d'utile, vous pouvez utiliser quelque chose comme le visualiseur de mémoire de Visual Studio pour afficher le contenu exact de la mémoire.
Kiley Naro
1
Même Google le fait, par exemple "-58 en binaire" - mais +1 pour vouloir savoir comment le faire vous-même dans le code.
Konrad Rudolph

Réponses:

420

Le moyen le plus simple est probablement de créer un std::bitsetreprésentant de la valeur, puis de le diffuser sur 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
la source
23
Ah, j'oublie toujours std::bitset! +1de moi.
sbi
2
Excusez mon ignorance, mais cela ne montrera-t-il que la représentation binaire d'un nombre (par exemple 8 serait 00001000) ou sa représentation en mémoire (par exemple comment -8 serait stocké en prenant soin du bit de signe et en utilisant le "complément à deux")?
Jesse Emond
12
L' bitsetargument constructeur de @Jesse: est interprété comme une valeur non signée, ce qui équivaut au complément à deux. À strictement parler, C ++ ne garantit pas l'arithmétique du complément à deux, et l' -58 >> 3opération dans votre exemple n'est pas définie.
Potatoswatter
Puis-je transtyper la valeur du jeu de bits (c'est-à-dire x ou y dans cet exemple) en char *?
nirvanaswap
1
Merci Jerry, j'ai découvert to_string quelques minutes plus tard. Pour info, le casting ne fonctionne pas, la variable de jeu de bits est un objet d'une classe de bitset3ul (?!) Vraiment arcane. Mieux vaut laisser les abstractions faire le travail!
nirvanaswap
102

Utilisez la conversion à la volée en std::bitset. Pas de variables temporaires, pas de boucles, pas de fonctions, pas de 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;
}

Tirages:

a = 11000110
b = 11111000
c = 1111111011000101
r233967
la source
6
Notez que la taille de codage en dur n'est pas nécessaire. Par exemple , pour imprimer xutilisation: std::cout << std::bitset<8*sizeof(x)>(x).
Apollys prend en charge Monica
25

Si vous souhaitez afficher la représentation binaire de n'importe quel objet, pas seulement un entier, n'oubliez pas de réinterpréter d'abord comme un tableau de caractères, alors vous pouvez imprimer le contenu de ce tableau, en hexadécimal, ou même en binaire (via le jeu 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);
}

Notez que la plupart des systèmes courants sont peu endiens, donc la sortie de show_binrep(c)n'est pas le 1111111 011000101 que vous attendez, car ce n'est pas ainsi qu'il est stocké en mémoire. Si vous recherchez une représentation de valeur en binaire, alors un simple cout << bitset<16>(c)fonctionne.

Cubbi
la source
11

Existe-t-il un moyen standard en C ++ d'afficher la représentation binaire en mémoire d'un nombre [...]?

Non, il n'y a pas std::bin, comme std::hexou std::dec, mais ce n'est pas difficile de sortir un nombre binaire vous-même:

Vous sortez le bit le plus à gauche en masquant tous les autres, décalage à gauche et répétez cela pour tous les bits que vous avez.

(Le nombre de bits dans un type est sizeof(T) * CHAR_BIT.)

sbi
la source
7

Similaire à ce qui est déjà publié, en utilisant simplement le décalage de bits et le masque pour obtenir le bit; utilisable pour tout type, étant un modèle ( seulement je ne sais pas s'il existe un moyen standard d'obtenir le nombre de bits en 1 octet, j'en ai utilisé 8 ici ).

#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
la source
3
La méthode standard pour obtenir le nombre de bits par octet est la macro CHAR_BIT.
R. Martinho Fernandes
Il semble que sbi ait édité le post de Εύδοξος selon le commentaire de @ R.MartinhoFernandes. Cependant, il n'a pas changé la dernière phrase. Je vais éditer.
gsamaras
3

Fonction réutilisable:

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

Usage:

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

Cela fonctionne avec toutes sortes d'entiers.

Shital Shah
la source
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
}
Ècris ton nom içi
la source
Ça ne devrait pas être ça int t = pow(2, num_of_bits - 1);?
BmyGuest
0

En utilisant l'ancienne version C ++, vous pouvez utiliser cet extrait:

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
la source
Impression du mauvais nombre de bits. 111 000 110 est 9 bits, pas 8.
David Ledger
J'ai fait une erreur de limite, veuillez vérifier maintenant
Ratah
0

Utilisation des réponses et des modèles de commodité std :: bitset:

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

L'utiliser comme ceci:

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;

Génère une sortie:

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

Voici la vraie façon d'obtenir une représentation binaire d'un nombre:

unsigned int i = *(unsigned int*) &x;
user5463518
la source
Non ; cela copie simplement x dans i. A moins que vous ne vouliez dire ça comme une blague?
AnthonyD973
-11

C'est ce que vous cherchez?

std::cout << std::hex << val << std::endl;
Kevin
la source
30
Note du modérateur J'ai essayé de purger sélectivement les commentaires antagonistes ou autrement non constructifs sous cette réponse, et je me suis retrouvé avec une conversation très brisée. Tous les commentaires ont été supprimés. Veuillez garder vos commentaires professionnels, constructifs et surtout sur le sujet. Si l'OP voulait le supprimer, l'OP l'aurait déjà supprimé. Si vous n'êtes pas d'accord avec cette réponse, votez. Si vous pouvez améliorer cette réponse, modifiez. </argument>. Vraiment, nous sommes adultes, oui? J'ai presque vérifié les âges sur tout ce qui a été commenté ici pour m'assurer que tout le monde avait plus de 13 ans.
Tim Post