Làm thế nào để in (sử dụng cout) một số ở dạng nhị phân?


215

Tôi đang theo một khóa học đại học về các hệ điều hành và chúng tôi đang học cách chuyển đổi từ nhị phân sang thập lục phân, thập phân sang thập lục phân, v.v. + 1).

Chúng tôi có một vài bài tập để làm trên giấy và tôi muốn có thể xác minh câu trả lời của mình trước khi gửi bài tập của mình cho giáo viên. Tôi đã viết một chương trình C ++ cho một vài bài tập đầu tiên nhưng bây giờ tôi bị mắc kẹt về cách tôi có thể xác minh câu trả lời của mình với vấn đề sau:

char a, b;

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

b = a >> 3;

và chúng ta cần để hiển thị các biểu diễn nhị phân trong bộ nhớ của a, bc.

Tôi đã thực hiện nó trên giấy và nó cho tôi các kết quả sau (tất cả các biểu diễn nhị phân trong bộ nhớ của các số sau phần bù của hai số):

a = 00111010 (đó là một char, vì vậy 1 byte)

b = 00001000 (đó là một char, vì vậy 1 byte)

c = 11111110 11000101 (ngắn, nên 2 byte)

Có cách nào để xác minh câu trả lời của tôi không? Có một cách tiêu chuẩn trong C ++ để hiển thị biểu diễn nhị phân trong bộ nhớ của một số hay tôi phải tự viết mã cho từng bước (tính toán phần bù của hai và sau đó chuyển đổi thành nhị phân)? Tôi biết cái sau sẽ không mất nhiều thời gian nhưng tôi tò mò liệu có cách nào chuẩn để làm như vậy không.


2
bạn có hiểu đại diện thập lục phân không? nếu bạn làm như vậy, bạn có thể in trình điều khiển hex (sử dụng std::hex) trình điều khiển - Tôi sẽ để nó như một bài tập để bạn giải quyết phần còn lại ...
Nim

3
Bạn nhấn mạnh "trong bộ nhớ" rất nhiều, nhưng tôi hy vọng họ sẽ không khiến bạn phải giải quyết các vấn đề về endian.
Đánh dấu tiền chuộc

Bạn có biết có bất kỳ ý tưởng nào về endianness là gì không? Nếu bạn làm, bạn có quan tâm đến nó cho bài tập này? Câu trả lời cho những câu hỏi này có thể ảnh hưởng đến câu trả lời cho câu hỏi của bạn.
R. Martinho Fernandes

Tùy thuộc vào IDE của bạn, nếu bạn chỉ muốn xác minh tính chính xác của giải pháp viết tay của mình và không thực sự viết chương trình để hiển thị nội dung hữu ích, bạn có thể sử dụng một cái gì đó như trình xem bộ nhớ của Visual Studio để xem nội dung chính xác của bộ nhớ.
Kiley Naro

1
Ngay cả Google cũng làm điều này, ví dụ như -58 trong nhị phân - nhưng +1 vì muốn tự mình tìm hiểu cách thực hiện mã.
Konrad Rudolph

Câu trả lời:


419

Cách dễ nhất có lẽ là tạo một std::bitsetđại diện cho giá trị, sau đó truyền phát nó đến 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
À, tôi cứ quên mất std::bitset! +1từ tôi.
sbi

2
Xin lỗi vì sự thiếu hiểu biết của tôi, nhưng điều này sẽ chỉ hiển thị biểu diễn nhị phân của một số (ví dụ 8 sẽ là 00001000) hoặc biểu diễn bộ nhớ của nó (ví dụ -8 sẽ được lưu trữ bằng cách chăm sóc bit dấu và sử dụng "phần bù hai")?
Jesse Emond

12
@Jlie: bitsetĐối số hàm tạo được hiểu là giá trị không dấu, hoạt động giống như phần bù của hai. Nói đúng ra, C ++ không đảm bảo số học bổ sung của hai và cũng -58 >> 3không xác định được thao tác trong ví dụ của bạn.
Potatoswatter

Tôi có thể đánh máy giá trị bitet (nghĩa là x hoặc y trong ví dụ này) thành char * không?
nirvanaswap

1
Cảm ơn Jerry, tôi đã phát hiện ra to_opes sau đó. FYI, quá trình truyền không hoạt động, biến bitet là một đối tượng của một số lớp bitet3ul (?!) Thực sự phức tạp. Tốt nhất để cho trừu tượng làm công việc!
nirvanaswap

102

Sử dụng chuyển đổi nhanh chóng để std::bitset. Không có biến tạm thời, không có vòng lặp, không có chức năng, không có macro.

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

Bản in:

a = 11000110
b = 11111000
c = 1111111011000101

6
Lưu ý rằng kích thước mã hóa cứng là không cần thiết. Ví dụ để in xsử dụng : std::cout << std::bitset<8*sizeof(x)>(x).
Apollys hỗ trợ Monica

25

Nếu bạn muốn hiển thị biểu diễn bit của bất kỳ đối tượng nào, không chỉ là số nguyên, hãy nhớ diễn giải lại dưới dạng mảng char trước, sau đó bạn có thể in nội dung của mảng đó, dưới dạng hex hoặc thậm chí dưới dạng nhị phân (thông qua bitet):

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

Lưu ý rằng hầu hết các hệ thống phổ biến là ít về cuối nhỏ, vì vậy sản lượng show_binrep(c)không những 1111111 011000101 bạn mong đợi, bởi vì đó không phải là cách nó được lưu trữ trong bộ nhớ. Nếu bạn đang tìm kiếm đại diện giá trị trong nhị phân, thì một cout << bitset<16>(c)công việc đơn giản .


11

Có cách nào chuẩn trong C ++ để hiển thị biểu diễn nhị phân trong bộ nhớ của một số [...] không?

Không. Không std::bin, giống như std::hexhoặc std::dec, nhưng không khó để tự xuất một số nhị phân:

Bạn xuất ra bit trái nhiều nhất bằng cách che dấu tất cả các bit khác, dịch chuyển trái và lặp lại điều đó cho tất cả các bit bạn có.

(Số lượng bit trong một loại là sizeof(T) * CHAR_BIT.)


7

Tương tự như những gì đã được đăng, chỉ cần sử dụng bit-shift và mặt nạ để lấy bit; có thể sử dụng cho bất kỳ loại nào, là một mẫu ( chỉ không chắc chắn nếu có một cách tiêu chuẩn để lấy số bit trong 1 byte, tôi đã sử dụng 8 ở đây ).

#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
Cách tiêu chuẩn để có được số bit trên mỗi byte là macro CHAR_BIT.
R. Martinho Fernandes

Dường như sbi đã chỉnh sửa bài đăng của bình luận theo nhận xét của @ R.MartinhoFernandes. Tuy nhiên, anh không thay đổi câu cuối cùng. Tôi sẽ chỉnh sửa.
gsamaras

3

Chức năng tái sử dụng:

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

Sử dụng:

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

Điều này hoạt động với tất cả các loại số nguyên.


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
}

Có nên int t = pow(2, num_of_bits - 1);không?
BmyGuest

0

Sử dụng phiên bản C ++ cũ, bạn có thể sử dụng đoạn mã này:

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

In sai số bit. 111 000 110 là 9 bit, không phải 8.
David Ledger

Tôi đã phạm sai lầm ranh giới, vui lòng kiểm tra ngay bây giờ
Ratah

0

Sử dụng câu trả lời std :: bitset và các mẫu tiện lợi:

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

Sử dụng nó như thế này:

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;

Tạo đầu ra:

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

-5

Đây là cách thực sự để có được biểu diễn nhị phân của một số:

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

Không; đây chỉ là bản sao x vào i. Trừ khi bạn có ý này như một trò đùa?
AnthonyD973

-11

Đây có phải là những gì bạn đang tìm kiếm?

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

30
Người điều hành Lưu ý Tôi đã cố gắng thanh lọc các ý kiến ​​đối kháng hoặc không mang tính xây dựng theo câu trả lời này một cách có chọn lọc và tôi đã kết thúc bằng một cuộc trò chuyện rất tan vỡ. Tất cả các ý kiến ​​đã được thanh trừng. Hãy giữ ý kiến ​​chuyên nghiệp, xây dựng và hầu hết tất cả về chủ đề. Nếu OP muốn loại bỏ điều này, OP sẽ xóa nó ngay bây giờ. Nếu bạn không đồng ý với câu trả lời này, thì hãy bỏ phiếu. Nếu bạn có thể cải thiện câu trả lời này, hãy chỉnh sửa. </argument>. Thực sự, chúng ta là người lớn, phải không? Tôi gần như đã kiểm tra độ tuổi trên tất cả những gì đã nhận xét ở đây để đảm bảo mọi người đều trên 13.
Tim Post
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.