İkili biçimde bir sayı nasıl yazdırılır (cout kullanılarak)?


215

İşletim sistemleri hakkında bir kolej dersini takip ediyorum ve ikilikten onaltılıya, ondalıktan onaltılıya vb. + 1).

Kağıt üzerinde yapacağımız birkaç alıştırma var ve çalışmalarımı öğretmene göndermeden önce cevaplarımı doğrulamak istiyorum. İlk birkaç alıştırma için bir C ++ programı yazdım ama şimdi cevabımı aşağıdaki sorunla nasıl doğrulayabileceğim konusunda sıkışıp kaldım:

char a, b;

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

b = a >> 3;

ve biz ikili gösterimini göstermek gerekir bellekte arasında a, bve c.

Ben kağıt üzerinde yaptım ve bana aşağıdaki sonuçları verir (ikisinin tamamlayıcı sonra sayıların hafızasında tüm ikili sunumlar):

a = 00111010 (bir karakter, yani 1 bayt)

b = 00001000 (bir karakter, yani 1 bayt)

c = 11111110 11000101 (kısa, yani 2 bayt)

Cevabımı doğrulamanın bir yolu var mı? C ++ 'da bir sayının belleğinde ikili temsili göstermek için standart bir yol var mı, ya da her adımı kendim kodlamak zorunda (ikisinin tamamlayıcı hesaplamak ve sonra ikili dönüştürmek)? İkincisinin çok uzun sürmeyeceğini biliyorum ama bunu yapmanın standart bir yolu olup olmadığını merak ediyorum.


2
onaltılık gösterimi anlıyor musunuz? yaparsanız, onaltılı temsili ( std::hexmanipülatör kullanarak ) yazdırabilirsiniz - gerisini halletmeniz için bir egzersiz olarak bırakacağım ...
Nim

3
"Bellekte" çok fazla vurgu yaparsınız, ama umarım endian sorunlarıyla ilgilenmezler.
Mark Ransom

Endianitenin ne olduğu hakkında bir fikriniz var mı? Eğer yaparsanız, bu egzersiz için onu önemsiyor musunuz? Bu soruların cevabı sorunuzun cevabını etkileyebilir.
R. Martinho Fernandes

IDE'nize bağlı olarak, sadece elle yazılmış çözümünüzün doğruluğunu doğrulamak ve gerçekten yararlı bir şey görüntülemek için bir program yazmak istemiyorsanız, belleğin tam içeriğini görüntülemek için Visual Studio'nun bellek görüntüleyicisi gibi bir şey kullanabilirsiniz.
Kiley Naro

1
Google bile bunu yapar, örneğin "-58 ikili" - ancak +1 kodunu kendiniz nasıl yapacağınızı öğrenmek için +1.
Konrad Rudolph

Yanıtlar:


419

En kolay yol muhtemelen std::bitsetdeğeri temsil eden bir değer oluşturmaktır ve sonra bunu akışa aktarmaktır 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
Ah, unutmaya devam ediyorum std::bitset! +1benden.
sbi

2
Cehaletimi affedin, ancak bu sadece bir sayının ikili gösterimini (örn. 8 00001000 olurdu) veya bellek gösterimini gösterecektir (örn. -8, işaret bitine dikkat ederek ve "ikinin tamamlayıcısı" kullanılarak nasıl saklanır)?
Jesse Emond

12
@Jesse: bitset'nin yapıcı argümanı, ikisinin tamamlayıcısıyla aynı olan işaretsiz bir değer olarak yorumlanır. Açıkça söylemek gerekirse, C ++ ikisinin tamamlayıcı aritmetiğini garanti etmez ve ayrıca -58 >> 3örneğinizdeki işlem tanımsızdır.
Potatoswatter

Bitset değerini (yani, bu örnekte x veya y) bir char * olarak yazabilir miyim?
nirvanaswap

1
Teşekkürler Jerry, birkaç dakika sonra keşfettim. FYI, döküm işe yaramıyor, bitset değişkeni gerçekten gizli görünümlü bitset3ul (?!) Sınıfının bir nesnesidir. Soyutlamaların işi yapmasına izin vermek en iyisi!
nirvanaswap

102

Anında anında dönüşümü kullanın std::bitset. Geçici değişken yok, döngü yok, işlev yok, makro yok.

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

Baskılar:

a = 11000110
b = 11111000
c = 1111111011000101

6
Sabit kodlama boyutunun gerekli olmadığını unutmayın. Örneğin yazdırmak için xkullanılmasını: std::cout << std::bitset<8*sizeof(x)>(x).
Apollys, Monica

25

Yalnızca bir tam sayı değil, herhangi bir nesnenin bit temsilini görüntülemek istiyorsanız, önce bir char dizisi olarak yeniden yorumlamayı unutmayın, o zaman dizinin içeriğini onaltılık, hatta ikili (bitset aracılığıyla) yazdırabilirsiniz:

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

Çıktısı böylece Not en yaygın sistemler, küçük endian olduğunu show_binrep(c)olduğunu değil beklediğiniz 1111111 011000101 o bellekte depolanır nasıl değil çünkü. İkili değer temsili arıyorsanız , o zaman basit bir cout << bitset<16>(c)iş.


11

C ++ bir sayının belleğinde ikili gösterimi göstermek için standart bir yolu var mı [...]?

Hayır. std::bin, Gibi std::hexveya yoktur , std::decancak kendiniz bir sayı ikilisi çıkarmak zor değildir:

En soldaki biti, diğerlerini maskeleyerek, sola kaydırıp, sahip olduğunuz tüm bitler için tekrarlayın.

(Bir türdeki bit sayısı sizeof(T) * CHAR_BIT.)


7

Daha önce yayınlananlara benzer şekilde, sadece bit almak için bit-shift ve maske kullanın; bir şablon olarak her tür için kullanılabilir ( sadece 1 baytta bit sayısını almanın standart bir yolu olup olmadığından emin değilim, burada 8 kullandım ).

#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
Bayt başına bit sayısını almanın standart yolu makrodur CHAR_BIT.
R. Martinho Fernandes

Görünüşe göre, sbi, @ R.MartinhoFernandes'ın yorumuna göre postοξος'un yayınını düzenledi. Ancak, son cümleyi değiştirmedi. Ben düzenleyeceğim.
gsamaras

3

Yeniden kullanılabilir fonksiyonu:

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

Kullanımı:

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

Bu her türlü tamsayı ile çalışır.


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
}

Olmamalı int t = pow(2, num_of_bits - 1);mı?
BmyGuest

0

Eski C ++ sürümünü kullanarak bu snippet'i kullanabilirsiniz:

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

Yanlış sayıda bit yazdırılıyor. 111000110, 8 değil, 9 bittir.
David Ledger

Sınır hatası yaptım, lütfen şimdi kontrol edin
Ratah

0

Std :: bitset cevapları ve kolaylık şablonlarını kullanma:

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

Bu şekilde kullanmak:

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;

Çıktı üretir:

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

-5

İşte bir sayının ikili temsilini almanın gerçek yolu:

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

Hayır ; bu sadece x'i i'ye kopyalar. Bunu bir şaka olarak kastetmedikçe?
AnthonyD973

-11

Bu aradığınız şey mi?

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

30
Moderatör Not ben denedim seçici Bu yanıt altında antagonistik veya başka türlü olmayan yapıcı yorumlar temizlemek için, ve ben çok kırık konuşma ile sona erdi. Tüm yorumlar tasfiye edildi. Lütfen konu hakkında yorumlarınızı profesyonel, yapıcı ve en önemlisi tutun. OP bunu kaldırmak isteseydi, OP şimdi kaldırmış olurdu. Bu yanıta katılmıyorsanız oy verin. Bu yanıtı geliştirebilirseniz düzenleyin. </argument>. Gerçekten yetişkiniz, değil mi? Neredeyse herkesin 13 yaşından büyük olduğundan emin olmak için burada yorumlanan tüm yaşları kontrol ettim.
Tim Post
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.