Як надрукувати (використовуючи cout) число у двійковій формі?


215

Я слідую за курсом коледжу з операційних систем, і ми вчимося, як перетворити з двійкових у шістнадцятковий, десятковий у шістнадцятковий і т.д. + 1).

У нас є кілька вправ, які потрібно зробити на папері, і я хотів би мати можливість перевірити свої відповіді, перш ніж подавати свою роботу вчителю. Я написав програму C ++ протягом перших кількох вправ, але тепер я затримався, як я міг перевірити свою відповідь за допомогою наступної проблеми:

char a, b;

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

b = a >> 3;

і ми повинні показати , двійкове подання в пам'яті про a, bі c.

Я це зробив на папері, і це дає мені наступні результати (всі двійкові представлення на пам'ять про числа після їх доповнення):

a = 00111010 (це знак, тому 1 байт)

b = 00001000 (це знак, тому 1 байт)

c = 11111110 11000101 (це короткий, тому 2 байти)

Чи є спосіб перевірити свою відповідь? Чи є стандартний спосіб в C ++ відображати бінарне представлення в пам'яті числа, або мені потрібно кодувати кожен крок самостійно (обчислюйте доповнення двох, а потім перетворюйте у бінарне)? Я знаю, що останнє не зайняло б так довго, але мені цікаво, чи існує стандартний спосіб зробити це.


2
ти розумієш шістнадцяткове представлення? якщо ви це зробите, ви можете роздрукувати шістнадцяткове представлення (використовуючи std::hex) маніпулятор - я залишаю це як вправу, щоб ви відпрацювали решту ...
Нім

3
Ви багато наголошуєте на "пам'яті", але я сподіваюся, що вони не змушують вас вирішувати ендіанські проблеми.
Марк Рансом

Чи знаєте ви, що маєте якесь уявлення про те, що таке витривалість? Якщо ви це робите, чи не піклуєтесь ви про цю вправу? Відповідь на ці запитання може вплинути на відповідь на ваше запитання.
Р. Мартіньо Фернандес

Залежно від вашого IDE, якщо ви просто хочете перевірити правильність рішення, написаного власноруч, а насправді не написати програму, щоб відобразити щось корисне, ви можете використовувати щось на зразок переглядача пам'яті Visual Studio для перегляду точного вмісту пам'яті.
Кілі Наро

1
Навіть Google робить це, наприклад, "-58 у двійковій формі" - але +1 за те, щоб дізнатися, як це зробити самостійно в коді.
Конрад Рудольф

Відповіді:


419

Найпростіший спосіб - це, мабуть, створити std::bitsetзначення, що представляє, а потім передати його 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
Ах, продовжую забувати std::bitset! +1від мене.
sbi

2
Вибачте моє незнання, але чи покаже це лише двійкове представлення числа (наприклад, 8 було б 00001000) або його представлення пам'яті (наприклад, як -8 буде зберігатися, піклуючись про біт знаків та використовуючи "доповнення двох")?
Джессі Емонд

12
Аргумент bitsetконструктора @Jesse: інтерпретується як непідписане значення, яке працює так само, як і доповнення двох. Строго кажучи, C ++ не гарантує арифметику комплементу двох, а також -58 >> 3операція у вашому прикладі не визначена.
Potatoswatter

Чи можу я набрати значення бітового набору (тобто x або y у цьому прикладі) до знака *?
nirvanaswap

1
Спасибі Джеррі, я виявив, що минуло хвилин після цього. FYI, кастинг не працює, змінна бітсета є об'єктом класу дійсно нецензурних bitset3ul (?!). Найкраще, щоб абстракції виконали роботу!
nirvanaswap

102

Використовуйте конверсію під час руху std::bitset. Ні тимчасових змінних, ні циклів, ні функцій, ні макросів.

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

Друкує:

a = 11000110
b = 11111000
c = 1111111011000101

6
Зауважте, що розмір жорсткого кодування не потрібен. Наприклад , для друку xвикористання: std::cout << std::bitset<8*sizeof(x)>(x).
Аполіс підтримує Моніку

25

Якщо ви хочете відобразити бітове представлення будь-якого об'єкта, а не лише цілого числа, не забудьте спершу інтерпретувати як масив char, тоді ви можете надрукувати вміст цього масиву як шістнадцятковий або навіть як двійковий (через бітсет):

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

Зверніть увагу , що більшість поширених систем прямий порядок байтів, тому вихід show_binrep(c)є НЕ 1111111 011000101 ви очікуєте, тому що це не так, як вона зберігається в пам'яті. Якщо ви шукаєте представлення значення у двійковій формі, то простий варіант cout << bitset<16>(c)працює.


11

Чи є стандартний спосіб в C ++ відображати бінарне представлення в пам'яті числа [...]?

Ні Ні . Там немає std::bin, як std::hexі std::dec, але це не так важко вивести число двійкових себе:

Виводить найменший лівий біт, маскуючи всі інші, зсуваючи ліворуч і повторюючи це для всіх бітів, які у вас є.

(Кількість бітів у типі є sizeof(T) * CHAR_BIT.)


7

Подібно до того, що вже розміщено, просто використовуючи біт-зсув та маску, щоб отримати біт; може бути використаний для будь-якого типу, будучи шаблоном ( тільки не впевнений, чи є стандартний спосіб отримати кількість біт в 1 байт, тут я використав 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
Стандартний спосіб отримати кількість біт на байт - макрос CHAR_BIT.
Р. Мартіньо Фернандес

Схоже, sbi редагував пост Εύδοξος відповідно до коментаря @ R.MartinhoFernandes. Однак останнє речення він не змінив. Я відредагую.
gsamaras

3

Багаторазова функція:

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

Використання:

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

Це працює з усіма видами цілих чисел.


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
}

Чи не повинно було бути int t = pow(2, num_of_bits - 1);?
BmyGuest

0

Використовуючи стару версію C ++, ви можете використовувати цей фрагмент:

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

Друк неправильної кількості біт. 111 000 110 - це 9 біт, а не 8.
Девід Леджер

Я допустив граничну помилку, будь ласка, перевірте зараз
Ratah

0

Використання відповідей 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;
}

Використовуючи це так:

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;

Отримує вихід:

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

-5

Ось справжній спосіб отримати двійкове представлення числа:

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

Немає ; це просто копіює x в i. Якщо ви не мали на увазі це як жарт?
AnthonyD973

-11

Це те, що ви шукаєте?

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

30
Модератор Примітка Я намагався вибирати антагоністичні або неконструктивні коментарі під цією відповіддю вибірково, і я закінчив дуже розбиту розмову. Усі коментарі були піддані. Будь ласка, зберігайте коментарі професійні, конструктивні та найбільше щодо теми. Якби ОП хотіла зняти це, ОР вже його видалила б. Якщо ви не згодні з цією відповіддю, тоді голосуйте. Якщо ви можете покращити цю відповідь, відредагуйте. </argument>. Дійсно, ми дорослі, так? Я майже перевіряв віки на всіх, що тут коментували, щоб переконатися, що всім було старше 13 років
Tim Post
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.