Pertanyaan Bagaimana saya mendapatkan data bit-demi-bit dari nilai integer dalam C?


Saya ingin mengekstrak bit angka desimal.

Sebagai contoh, 7 adalah biner 0111, dan saya ingin mendapatkan 0 1 1 1 semua bit yang disimpan dalam bool. Bagaimana saya bisa melakukannya?

OK, loop bukan pilihan yang bagus, bisakah saya melakukan hal lain untuk ini?


76
2018-02-12 04:51


asal


Jawaban:


Jika Anda ingin bit k-th dari n, kemudian lakukan

(n & ( 1 << k )) >> k

Di sini kita membuat topeng, menerapkan topeng ke n, dan kemudian langsung menggeser nilai bertopeng untuk mendapatkan hanya sedikit yang kita inginkan. Kita bisa menulisnya lebih lengkap sebagai:

    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;

Anda dapat membaca lebih lanjut tentang bit-masking sini.

Berikut ini programnya:

#include <stdio.h>
#include <stdlib.h>

int *get_bits(int n, int bitswanted){
  int *bits = malloc(sizeof(int) * bitswanted);

  int k;
  for(k=0; k<bitswanted; k++){
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

int main(){
  int n=7;

  int  bitswanted = 5;

  int *bits = get_bits(n, bitswanted);

  printf("%d = ", n);

  int i;
  for(i=bitswanted-1; i>=0;i--){
    printf("%d ", bits[i]);
  }

  printf("\n");
}

120
2018-02-12 04:54



Seperti yang diminta, saya memutuskan untuk memperpanjang komentar saya pada jawaban telunjuk ke jawaban penuh. Meskipun jawabannya benar, itu tidak perlu rumit. Selanjutnya semua jawaban saat ini menggunakan ditandatangani ints untuk mewakili nilai-nilai. Ini berbahaya, karena pengalihan nilai negatif yang benar adalah yang ditentukan oleh penerapan (bukan portabel) dan pengalihan ke kiri dapat menyebabkan perilaku tidak terdefinisi (lihat pertanyaan ini).

Dengan menggeser bit yang diinginkan ke posisi bit paling tidak signifikan, masking dapat dilakukan dengan 1. Tidak perlu menghitung nilai mask baru untuk setiap bit.

(n >> k) & 1

Sebagai program yang lengkap, menghitung (dan kemudian mencetak) suatu array nilai bit tunggal:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    unsigned
        input = 0b0111u,
        n_bits = 4u,
        *bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
        bit = 0;

    for(bit = 0; bit < n_bits; ++bit)
        bits[bit] = (input >> bit) & 1;

    for(bit = n_bits; bit--;)
        printf("%u", bits[bit]);
    printf("\n");

    free(bits);
}

Dengan asumsi bahwa Anda ingin menghitung semua bit seperti dalam kasus ini, dan bukan yang spesifik, loop dapat diubah lebih lanjut menjadi

for(bit = 0; bit < n_bits; ++bit, input >>= 1)
    bits[bit] = input & 1;

Ini memodifikasi input di tempat dan dengan demikian memungkinkan penggunaan lebar konstan, pergeseran satu bit, yang mungkin lebih efisien pada beberapa arsitektur.


57
2017-10-07 07:16



Inilah satu cara untuk melakukannya — ada banyak lainnya:

bool b[4];
int v = 7;  // number to dissect

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));

3
2018-02-12 04:55



Inilah cara yang sangat sederhana untuk melakukannya;

int main()
{
    int s=7,l=1;
    vector <bool> v;
    v.clear();
    while (l <= 4)
    {
        v.push_back(s%2);
        s /= 2;
        l++;
    }
    for (l=(v.size()-1); l >= 0; l--)
    {
        cout<<v[l]<<" ";
    }
    return 0;
}

2
2018-02-12 05:02



@prateek terima kasih atas bantuan Anda. Saya menulis ulang fungsi dengan komentar untuk digunakan dalam program. Tingkatkan 8 untuk lebih banyak bit (hingga 32 untuk integer).

std::vector <bool> bits_from_int (int integer)    // discern which bits of PLC codes are true
{
    std::vector <bool> bool_bits;

    // continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
    for (int i = 0; i < 8; i++)
    {
        bool_bits.push_back (integer%2);    // remainder of dividing by 2
        integer /= 2;    // integer equals itself divided by 2
    }

    return bool_bits;
}

1
2018-02-24 18:52



Jika Anda tidak ingin ada putaran, Anda harus menuliskannya:

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    int num = 7;

    #if 0
        bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
    #else
        #define BTB(v,i) ((v) & (1u << (i))) ? true : false
        bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
        #undef BTB
    #endif

    printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);

    return 0;
}

Seperti yang ditunjukkan di sini, ini juga berfungsi di penginisialisasi.


1
2018-05-20 11:17



Menggunakan std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();

1
2018-05-12 14:47



#include <stdio.h>

int main(void)
{
    int number = 7; /* signed */
    int vbool[8 * sizeof(int)];
    int i;
        for (i = 0; i < 8 * sizeof(int); i++)
        {
            vbool[i] = number<<i < 0;   
            printf("%d", vbool[i]);
        }
    return 0;
}

0
2018-05-20 02:55