Jak wydrukować (za pomocą cout) liczbę w postaci binarnej?


215

Uczęszczam na kurs college'u na temat systemów operacyjnych i uczymy się, jak konwertować z binarnego na szesnastkowy, dziesiętny na szesnastkowy itp., A dziś właśnie dowiedzieliśmy się, jak liczby podpisane / niepodpisane są przechowywane w pamięci za pomocą uzupełnienia do dwóch (~ liczba + 1).

Mamy kilka ćwiczeń do zrobienia na papierze i chciałbym móc zweryfikować moje odpowiedzi przed przesłaniem mojej pracy nauczycielowi. Napisałem program C ++ dla kilku pierwszych ćwiczeń, ale teraz utknąłem, jak mogę zweryfikować swoją odpowiedź z następującym problemem:

char a, b;

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

b = a >> 3;

i musimy pokazać binarną reprezentację w pamięci z a, bi c.

Zrobiłem to na papierze i daje mi następujące wyniki (wszystkie reprezentacje binarne w pamięci liczb po uzupełnieniu do dwóch):

a = 00111010 (to znak, więc 1 bajt)

b = 00001000 (to znak, więc 1 bajt)

c = 11111110 11000101 (jest krótki, więc 2 bajty)

Czy istnieje sposób na zweryfikowanie mojej odpowiedzi? Czy istnieje standardowy sposób w C ++ do wyświetlania reprezentacji binarnej w pamięci liczby, czy też muszę kodować każdy krok osobno (obliczać uzupełnienie dwóch, a następnie konwertować na binarny)? Wiem, że ten ostatni nie potrwa tak długo, ale jestem ciekawy, czy istnieje standardowy sposób, aby to zrobić.


2
rozumiesz reprezentację szesnastkową? jeśli to zrobisz, możesz wydrukować reprezentację szesnastkową (za pomocą std::hex) manipulatora - Zostawię to jako ćwiczenie dla ciebie, aby opracować resztę ...
— Nim

3
Kładziecie duży nacisk na „w pamięci”, ale mam nadzieję, że nie zmuszają was do radzenia sobie z problemami endian.
— Mark Ransom,

Czy wiesz, co to jest endianizm? Jeśli tak, czy zależy ci na tym ćwiczeniu? Odpowiedź na te pytania może wpłynąć na odpowiedź na twoje pytanie.
— R. Martinho Fernandes,

W zależności od IDE, jeśli chcesz tylko zweryfikować poprawność swojego odręcznego rozwiązania, a nie piszesz programu wyświetlającego coś pożytecznego, możesz użyć czegoś takiego jak przeglądarka pamięci Visual Studio, aby wyświetlić dokładną zawartość pamięci.
— Kiley Naro,

1
Nawet Google robi to, na przykład „-58 w pliku binarnym” - ale +1 za chęć dowiedzenia się, jak to zrobić w kodzie.
— Konrad Rudolph,

Odpowiedzi:


419

Najłatwiejszym sposobem jest prawdopodobnie utworzenie std::bitsetreprezentującej wartości, a następnie przesłanie jej strumieniowo 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
Ach, ciągle o tym zapominam std::bitset! +1ode mnie.
— sbi

2
Przepraszam za moją ignorancję, ale czy to pokaże tylko binarną reprezentację liczby (np. 8 to 00001000) lub jej reprezentację pamięci (np. Jak -8 byłoby przechowywane przez dbanie o bit znaku i użycie „uzupełnienia do dwóch”)?
— Jesse Emond,

12
Argument bitsetkonstruktora @Jesse: jest interpretowany jako wartość bez znaku, która działa tak samo jak uzupełnienie do dwóch. Ściśle mówiąc, C ++ nie gwarantuje arytmetyki dopełniania dwóch, a także -58 >> 3operacja w twoim przykładzie jest niezdefiniowana.
— Potatoswatter

Czy mogę typecastować wartość zestawu bitów (tj. X lub y w tym przykładzie) na char *?
— nirvanaswap

1
Dzięki Jerry, odkryłem to_string kilka minut później. FYI, rzutowanie nie działa, zmienna zestawu bitów jest obiektem jakiejś naprawdę wyglądającej tajemniczo klasy bitset3ul (?!). Najlepiej, aby abstrakcje wykonały pracę!
— nirvanaswap

102

Użyj konwersji w locie do std::bitset. Bez zmiennych tymczasowych, bez pętli, bez funkcji, bez makr.

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

Wydruki:

a = 11000110
b = 11111000
c = 1111111011000101

6
Należy pamiętać, że rozmiar na stałe nie jest konieczny. Np wydrukować xużycie: std::cout << std::bitset<8*sizeof(x)>(x).
— Apollys wspiera Monikę

25

Jeśli chcesz wyświetlić bitową reprezentację dowolnego obiektu, a nie tylko liczby całkowitej, pamiętaj, aby najpierw ponownie zinterpretować jako tablicę char, a następnie możesz wydrukować zawartość tej tablicy, w postaci szesnastkowej lub nawet binarnej (za pomocą zestawu bitów):

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

Zauważ, że najbardziej popularne systemy to little-endian, więc wynik nieshow_binrep(c) jest 1111111 011000101, którego oczekujesz, ponieważ nie tak zachowuje się w pamięci. Jeśli szukasz reprezentacji wartości w formacie binarnym, to proste działa.cout << bitset<16>(c)


11

Czy w C ++ istnieje standardowy sposób wyświetlania reprezentacji binarnej w pamięci liczby [...]?

Nie. Nie ma std::bin, jak std::hexlub std::dec, ale nie jest trudno samemu wyprowadzić binarną liczbę:

Wyprowadzasz bit najbardziej w lewo, maskując wszystkie pozostałe, przesuwając w lewo i powtarzając to dla wszystkich bitów, które masz.

(Liczba bitów w typie to sizeof(T) * CHAR_BIT.)


7

Podobnie do tego, co zostało już opublikowane, wystarczy użyć bit-shift i maski, aby uzyskać bit; użyteczny dla dowolnego typu, będąc szablonem ( tylko nie jestem pewien, czy istnieje standardowy sposób na uzyskanie liczby bitów w 1 bajcie, użyłem tutaj 8 ).

#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
Standardowym sposobem na uzyskanie liczby bitów na bajt jest makro CHAR_BIT.
— R. Martinho Fernandes,

Wygląda na to, że sbi zredagował post Εύδοξος zgodnie z komentarzem @ R.MartinhoFernandes. Nie zmienił jednak ostatniego zdania. Będę edytować.
— gsamaras

3

Funkcja wielokrotnego użytku:

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

Stosowanie:

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

Działa to z wszelkiego rodzaju liczbami całkowitymi.


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
}

Nie powinno tak być int t = pow(2, num_of_bits - 1);?
— BmyGuest,

0

Korzystając ze starej wersji C ++, możesz użyć tego fragmentu:

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

Drukowanie niewłaściwej liczby bitów. 111 000 110 to 9 bitów, a nie 8.
— David Ledger

Popełniłem błąd na granicy, sprawdź teraz
— Ratah

0

Korzystanie z odpowiedzi std :: bitset i szablonów wygody:

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

Używając tego w ten sposób:

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;

Generuje dane wyjściowe:

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

-5

Oto prawdziwy sposób uzyskania binarnej reprezentacji liczby:

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

Nie; to po prostu kopiuje x do i. Chyba że miałeś na myśli to jako żart?
— AnthonyD973,

-11

Czy tego szukasz?

std::cout << std::hex << val << std::endl;

30
Moderator Uwaga I próbował oczyścić antagonistyczne lub niecenzuralna konstruktywnych komentarzy pod tą odpowiedzią selektywnie, a skończyło się z bardzo łamanego rozmowy. Wszystkie komentarze zostały usunięte. Komentarze powinny być profesjonalne, konstruktywne, a przede wszystkim na temat. Gdyby PO chciał to usunąć, OP już by go usunął. Jeśli nie zgadzasz się z tą odpowiedzią, głosuj. Jeśli możesz poprawić tę odpowiedź, edytuj. </argument>. Naprawdę jesteśmy dorośli, tak? Prawie sprawdziłem wiek wszystkich komentowanych tutaj, aby upewnić się, że wszyscy ukończyli 13 lat.
— Tim Post
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.