Bagaimana cara mencetak (menggunakan cout) suatu angka dalam bentuk biner?

215

Saya mengikuti kursus perguruan tinggi tentang sistem operasi dan kami belajar bagaimana mengkonversi dari biner ke heksadesimal, desimal menjadi heksadesimal, dll. Dan hari ini kami baru belajar bagaimana angka yang ditandatangani / tidak ditandai disimpan dalam memori menggunakan komplemen dua (~ number +1

Kami memiliki beberapa latihan untuk dilakukan di atas kertas dan saya ingin dapat memverifikasi jawaban saya sebelum mengirimkan pekerjaan saya kepada guru. Saya menulis program C ++ untuk beberapa latihan pertama, tetapi sekarang saya buntu bagaimana saya bisa memverifikasi jawaban saya dengan masalah berikut:

char a, b;

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

b = a >> 3;

dan kita harus menunjukkan representasi biner dalam memori dari a, bdan c.

Saya sudah melakukannya di atas kertas dan memberi saya hasil berikut (semua representasi biner dalam memori angka setelah komplemen keduanya):

a = 00111010 (ini char, jadi 1 byte)

b = 00001000 (ini char, jadi 1 byte)

c = 11111110 11000101 (pendek, jadi 2 byte)

Apakah ada cara untuk memverifikasi jawaban saya? Apakah ada cara standar dalam C ++ untuk menunjukkan representasi biner dalam memori angka, atau apakah saya harus mengkodekan setiap langkah sendiri (menghitung komplemen dua dan kemudian dikonversi ke biner)? Saya tahu yang terakhir tidak akan lama, tetapi saya ingin tahu apakah ada cara standar untuk melakukannya.

Jesse Emond
sumber
2
Anda mengerti representasi heksadesimal? jika Anda melakukannya, Anda dapat mencetak representasi hex (menggunakan std::hex) manipulator - Saya akan membiarkannya sebagai latihan bagi Anda untuk menyelesaikan sisanya ...
Nim
3
Anda banyak menekankan "dalam ingatan", tapi saya harap mereka tidak membuat Anda berurusan dengan masalah endian.
Mark Ransom
Apakah Anda tahu punya gagasan tentang apa itu endianness? Jika ya, apakah Anda peduli untuk latihan ini? Jawaban atas pertanyaan-pertanyaan ini dapat memengaruhi jawaban atas pertanyaan Anda.
R. Martinho Fernandes
Bergantung pada IDE Anda, jika Anda hanya ingin memverifikasi kebenaran dari solusi tulisan tangan Anda dan tidak benar-benar menulis program untuk menampilkan sesuatu yang bermanfaat, Anda dapat menggunakan sesuatu seperti penampil memori Visual Studio untuk melihat isi memori yang tepat.
Kiley Naro
1
Bahkan Google melakukan ini, misalnya "-58 dalam biner" - tetapi +1 karena ingin mengetahui bagaimana melakukannya sendiri dalam kode.
Konrad Rudolph

Jawaban:

419

Cara termudah mungkin adalah membuat nilai std::bitsetmewakili, lalu streaming itu ke 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
sumber
23
Ah, aku selalu lupa std::bitset! +1dari saya.
sbi
2
Maafkan ketidaktahuan saya, tetapi apakah ini hanya akan menampilkan representasi biner dari angka (misalnya 8 akan menjadi 00001000) atau representasi memorinya (misalnya bagaimana -8 akan disimpan dengan merawat bit tanda dan menggunakan "komplemen dua")?
Jesse Emond
12
bitsetArgumen konstruktor @Jesse: diartikan sebagai nilai yang tidak ditandatangani, yang berfungsi sama dengan komplemen dua. Sebenarnya, C ++ tidak menjamin aritmatika komplemen dua, dan juga -58 >> 3operasi dalam contoh Anda tidak terdefinisi.
Potatoswatter
Bisakah saya mengetikkan nilai bitet (yaitu, x atau y dalam contoh ini) ke char *?
nirvanaswap
1
Terima kasih Jerry, saya menemukan to_string beberapa menit kemudian. FYI, casting tidak bekerja, variabel bitset adalah objek dari kelas bitset3ul (?!) Yang benar-benar terlihat misterius. Terbaik untuk membiarkan abstraksi melakukan pekerjaan!
nirvanaswap
102

Gunakan konversi on-the-fly ke std::bitset. Tidak ada variabel sementara, tidak ada loop, tidak ada fungsi, tidak ada makro.

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

Cetakan:

a = 11000110
b = 11111000
c = 1111111011000101
r233967
sumber
6
Perhatikan bahwa ukuran hard-coding tidak diperlukan. Misalnya untuk mencetak xdigunakan: std::cout << std::bitset<8*sizeof(x)>(x).
Apollys mendukung Monica
25

Jika Anda ingin menampilkan representasi bit dari objek apa pun, bukan hanya bilangan bulat, ingat untuk menginterpretasikan ulang sebagai array char terlebih dahulu, kemudian Anda dapat mencetak konten array itu, sebagai hex, atau bahkan sebagai biner (via bitset):

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

Perhatikan bahwa kebanyakan sistem umum adalah little-endian, sehingga output dari show_binrep(c)ini tidak dengan 1111111 011000101 Anda harapkan, karena itu bukan bagaimana itu disimpan dalam memori. Jika Anda mencari representasi nilai dalam biner, maka cout << bitset<16>(c)karya sederhana .

Cubbi
sumber
11

Apakah ada cara standar dalam C ++ untuk menunjukkan representasi biner dalam memori nomor [...]?

Tidak ada std::bin, sepertistd::hex ataustd::dec , tetapi tidak sulit untuk menghasilkan biner angka sendiri:

Anda menampilkan bit paling kiri dengan menutupi semua yang lain, menggeser ke kiri, dan mengulanginya untuk semua bit yang Anda miliki.

(Jumlah bit dalam suatu tipe adalah sizeof(T) * CHAR_BIT.)

sbi
sumber
7

Mirip dengan apa yang sudah diposting, hanya menggunakan bit-shift dan mask untuk mendapatkan bit; dapat digunakan untuk semua jenis, menjadi templat ( hanya tidak yakin apakah ada cara standar untuk mendapatkan jumlah bit dalam 1 byte, saya menggunakan 8 di sini ).

#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
sumber
3
Cara standar untuk mendapatkan jumlah bit per byte adalah makro CHAR_BIT.
R. Martinho Fernandes
Tampaknya sbi mengedit pos ςοξος menurut komentar @ R.MartinhoFernandes. Namun, dia tidak mengubah kalimat terakhir. Saya akan mengedit.
gsamaras
3

Fungsi yang dapat digunakan kembali:

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

Pemakaian:

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

Ini bekerja dengan semua jenis bilangan bulat.

Shital Shah
sumber
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
}
Tulis Nama Anda Di Sini
sumber
Bukankah seharusnya begitu int t = pow(2, num_of_bits - 1);?
BmyGuest
0

Menggunakan versi C ++ lama, Anda dapat menggunakan potongan ini:

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
sumber
Mencetak jumlah bit yang salah. 111 000 110 adalah 9 bit, bukan 8.
David Ledger
Saya membuat kesalahan batas, silakan periksa sekarang
Ratah
0

Menggunakan std :: bitset jawaban dan templat kenyamanan:

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

Menggunakannya seperti ini:

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;

Menghasilkan output:

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

Berikut adalah cara yang benar untuk mendapatkan representasi biner dari angka:

unsigned int i = *(unsigned int*) &x;
pengguna5463518
sumber
Tidak ; ini hanya menyalin x ke i. Kecuali Anda maksud ini sebagai lelucon?
AnthonyD973
-11

Apakah ini yang Anda cari?

std::cout << std::hex << val << std::endl;
Kevin
sumber
30
Moderator Catatan Saya mencoba membersihkan komentar yang antagonis atau tidak konstruktif di bawah jawaban ini secara selektif, dan saya berakhir dengan percakapan yang sangat kacau. Semua komentar dihapus. Harap jaga komentar tetap profesional, konstruktif, dan terutama tentang topik. Jika OP ingin menghapus ini, OP akan menghapusnya sekarang. Jika Anda tidak setuju dengan jawaban ini, maka pilih. Jika Anda dapat meningkatkan jawaban ini, edit. </argument>. Sungguh, kita orang dewasa, ya? Saya hampir memeriksa usia pada semua yang berkomentar di sini untuk memastikan semua orang lebih dari 13.
Tim Post