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

Jesse Emond
źródło
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';
Jerry Coffin
źródło
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
r233967
źródło
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)

Cubbi
źródło
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.)

sbi
źródło
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);
    }
}
eudoksos
źródło
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.

Shital Shah
źródło
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
}
Napisz swoje imię
źródło
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
Ratah
źródło
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
użytkownik5673656
źródło
-5

Oto prawdziwy sposób uzyskania binarnej reprezentacji liczby:

unsigned int i = *(unsigned int*) &x;
użytkownik5463518
źródło
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;
Kevin
źródło
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