Как напечатать (используя cout) число в двоичном виде?

216

Я учусь в колледже на курсах по операционным системам, и мы учимся, как преобразовывать двоичные числа в шестнадцатеричные, десятичные в шестнадцатеричные и т. Д., И сегодня мы только что узнали, как числа со знаком / без знака хранятся в памяти с помощью дополнения к двум (~ число +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) манипулятор - я оставлю это в качестве упражнения для вас, чтобы поработать над остальными ...
Nim
3
Вы много подчеркиваете «в памяти», но я надеюсь, что они не заставляют вас иметь дело с порядком байтов.
Марк Рэнсом
Знаете ли вы, есть представление о порядке байтов? Если вы делаете, заботитесь ли вы об этом упражнении? Ответ на эти вопросы может повлиять на ответ на ваш вопрос.
Р. Мартиньо Фернандес
В зависимости от вашей среды IDE, если вы просто хотите проверить правильность написанного от руки решения и фактически не пишете программу для отображения чего-либо полезного, вы можете использовать что-то вроде средства просмотра памяти Visual Studio для просмотра точного содержимого памяти.
Кили Наро
1
Даже Google делает это, например, «-58 в двоичном формате» - но +1 за желание выяснить, как сделать это самостоятельно в коде.
Конрад Рудольф

Ответы:

420

Возможно, самый простой способ - создать 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от меня.
ВОО
2
Извините за мое невежество, но покажет ли это только двоичное представление числа (например, 8 будет 00001000) или его представление в памяти (например, как -8 будет храниться, заботясь о знаковом бите и используя «дополнение двух»)?
Джесси Эмонд
12
Аргумент bitsetконструктора @Jesse: интерпретируется как значение без знака, которое работает так же, как дополнение к двум. Строго говоря, C ++ не гарантирует арифметику с двумя дополнениями, а также -58 >> 3операция в вашем примере не определена.
Potatoswatter
Можно ли типизировать значение набора битов (например, x или y в этом примере) в символ *?
Nirvanaswap
1
Спасибо, Джерри, я обнаружил несколько минут спустя. К вашему сведению, приведение не работает, переменная bitset является объектом некоторого действительно загадочного класса 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
r233967
источник
6
Обратите внимание, что жесткий размер кода не требуется. Например , для печати xиспользования: std::cout << std::bitset<8*sizeof(x)>(x).
Аполлис поддерживает Монику
25

Если вы хотите отобразить битовое представление любого объекта, а не просто целое число, не забудьте сначала переосмыслить его как массив символов, затем вы можете распечатать содержимое этого массива в шестнадцатеричном или даже двоичном виде (с помощью набора битов):

#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)работает.

Cubbi
источник
11

Есть ли в C ++ стандартный способ показать двоичное представление в памяти числа [...]?

Нет, нет std::bin, вроде std::hexилиstd::dec , но нетрудно вывести двоичный номер самостоятельно:

Вы выводите самый левый бит, маскируя все остальные, сдвигая влево, и повторяете это для всех битов, которые у вас есть.

(Количество битов в типе равно sizeof(T) * CHAR_BIT.)

SBI
источник
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);
    }
}
eudoxos
источник
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
user5673656
источник
-5

Вот верный способ получить двоичное представление числа:

unsigned int i = *(unsigned int*) &x;
user5463518
источник
Нет; это просто копирует х в я. Разве вы не имели в виду это как шутку?
AnthonyD973
-11

Это то, что вы ищете?

std::cout << std::hex << val << std::endl;
Kevin
источник
30
Заметка модератора. Я попытался выборочно удалить антагонистические или иные неконструктивные комментарии по этому ответу, и в результате я получил очень оборванный разговор. Все комментарии были удалены. Пожалуйста, оставляйте комментарии профессиональными, конструктивными и больше всего по теме. Если бы ОП хотел удалить это, ОП уже удалил бы его. Если вы не согласны с этим ответом, то проголосуйте. Если вы можете улучшить этот ответ, отредактируйте. </argument>, Действительно, мы взрослые, да? Я почти проверил возраст всего, что прокомментировал здесь, чтобы убедиться, что всем было по 13 лет.
Тим Пост