C reverse bits in unsigned integer

前端 未结 12 800
一整个雨季
一整个雨季 2020-11-30 10:18

I\'m converting an unsigned integer to binary using bitwise operators, and currently do integer & 1 to check if bit is 1 or 0 and output, then right shift by 1 to divide

相关标签:
12条回答
  • 2020-11-30 10:53

    You could reverse the bits like you output them, and instead store them in another integer, and do it again :

    for (i = 0; i < (sizeof(unsigned int) * CHAR_BIT); i++)
    {
      new_int |= (original_int & 1);
      original_int = original_int >> 1;
      new_int = new_int << 1;
    }
    

    Or you could just do the opposite, shift your mask :

    unsigned int mask = 1 << ((sizeof(unsigned int) * CHAR_BIT) - 1);
    while (mask > 0)
    {
      bit = original_int & mask;
      mask = mask >> 1;
      printf("%d", (bit > 0));
    }
    

    If you want to remove leading 0's you can either wait for a 1 to get printed, or do a preliminary go-through :

    unsigned int mask = 1 << ((sizeof(unsigned int) * CHAR_BIT) - 1);
    while ((mask > 0) && ((original_int & mask) == 0))
      mask = mask >> 1;
    do
    {
      bit = original_int & mask;
      mask = mask >> 1;
      printf("%d", (bit > 0));
    } while (mask > 0);
    

    this way you will place the mask on the first 1 to be printed and forget about the leading 0's

    But remember : printing the binary value of an integer can be done just with printf

    0 讨论(0)
  • 2020-11-30 10:57

    You can reverse an unsigned 32-bit integer and return using the following reverse function :

    unsigned int reverse(unsigned int A) {
        unsigned int B = 0;
        for(int i=0;i<32;i++){
            unsigned int j = pow(2,31-i);
            if((A & (1<<i)) == (1<<i)) B += j; 
        }
    return B; 
    }
    

    Remember to include the math library. Happy coding :)

    0 讨论(0)
  • 2020-11-30 10:58

    I believe the question is asking how to not output in reverse order.

    Fun answer (recursion):

    #include <stdio.h>
    
    void print_bits_r(unsigned int x){
        if(x==0){
           printf("0");
           return;
        }
        unsigned int n=x>>1;
        if(n!=0){
           print_bits_r(n);
        }
        if(x&1){
            printf("1");
        }else{
            printf("0");
        }
    }
    
    
    void print_bits(unsigned int x){
        printf("%u=",x);
        print_bits_r(x);
        printf("\n");
    }
    
    int main(void) {
        print_bits(10u);//1010
        print_bits((1<<5)+(1<<4)+1);//110001
        print_bits(498598u);//1111001101110100110
        return 0;
    }
    

    Expected output:

    10=1010
    49=110001
    498598=1111001101110100110
    

    Sequential version (picks off the high-bits first):

    #include <limits.h>//Defines CHAR_BIT
    //....
    void print_bits_r(unsigned int x){
        //unsigned int mask=(UINT_MAX>>1)+1u;//Also works...
        unsigned int mask=1u<<(CHAR_BIT*sizeof(unsigned int)-1u);
        int start=0;
        while(mask!=0){
            if((x&mask)!=0){
                printf("1");
                start=1;
            }else{
                if(start){
                    printf("0");
                }
            }
            mask>>=1;
        }
        if(!start){
           printf("0");
        }    
    }
    
    0 讨论(0)
  • 2020-11-30 10:59

    Here's my bit shift version which I think is very concise. Does not work with leading zeros though. The main idea is as follows

    • Input is in variable a, final answer in b

    • Keep extracting the right most bit from a using (a&1)

    • OR that with b and left shift b to make place for the next bit

    • Right shift a to go to the next bit

       #include <stdio.h>
      
       void main()
       {
         int a = 23;
         int b = 0;
         while(a!=0)
         {
           b = (b<<1)|(a&1);
           a = a>>1;
         }
         printf("reversed bits gives %d\n", b);
        }
      
    0 讨论(0)
  • 2020-11-30 11:00

    Here's a golang version of reverse bits in an integer, if anyone is looking for one. I wrote this with an approach similar to string reverse in c. Going over from bits 0 to 15 (31/2), swap bit i with bit (31-i). Please check the following code.

    package main
    import "fmt"
    
    func main() {
        var num = 2
        //swap bits at index i and 31-i for i between 0-15
        for i := 0; i < 31/2; i++ {
            swap(&num, uint(i))
        }
        fmt.Printf("num is %d", num)
    }
    
    //check if bit at index is set
    func isSet(num *int, index uint) int {
        return *num & (1 << index)
    }
    
    //set bit at index
    func set(num *int, index uint) {
        *num = *num | (1 << index)
    }
    
    //reset bit at index
    func reSet(num *int, index uint) {
        *num = *num & ^(1 << index)
    }
    
    //swap bits on index and 31-index
    func swap(num *int, index uint) {
        //check index and 31-index bits
        a := isSet(num, index)
        b := isSet(num, uint(31)-index)
        if a != 0 {
            //bit at index is 1, set 31-index
            set(num, uint(31)-index)
        } else {
            //bit at index is 0, reset 31-index
            reSet(num, uint(31)-index)
        }
        if b != 0 {
            set(num, index)
        } else {
            reSet(num, index)
        }
    }`
    
    0 讨论(0)
  • 2020-11-30 11:03

    Reversing the bits in a word is annoying and it's easier just to output them in reverse order. E.g.,

    void write_u32(uint32_t x)
    {
        int i;
        for (i = 0; i < 32; ++i)
            putchar((x & ((uint32_t) 1 << (31 - i)) ? '1' : '0');
    }
    

    Here's the typical solution to reversing the bit order:

    uint32_t reverse(uint32_t x)
    {
        x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1);
        x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2);
        x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4);
        x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8);
        x = ((x >> 16) & 0xffffu) | ((x & 0xffffu) << 16);
        return x;
    }
    
    0 讨论(0)
提交回复
热议问题