2012-02-04 99 views
9

Tôi đang chuyển đổi số nguyên chưa dấu sang nhị phân sử dụng toán tử bitwise, và hiện đang làm số nguyên & 1 để kiểm tra xem bit là 1 hay 0 và đầu ra, sau đó phải dịch bằng 1 để chia cho 2. Tuy nhiên các bit được trả về theo thứ tự sai (ngược lại), vì vậy tôi đã đảo ngược thứ tự bit trong số nguyên trước khi bắt đầu.C bit đảo ngược trong số nguyên không dấu

Có cách nào đơn giản để thực hiện việc này không?

Ví dụ: Vì vậy, nếu tôi đưa ra unsigned int 10 = 1010

while (x not eq 0) 
    if (x & 1) 
    output a '1' 
    else 
    output a '0' 
    right shift x by 1 

này trả về 0101 đó là không chính xác ... vì vậy tôi đã suy nghĩ để đảo ngược thứ tự của các bit ban đầu trước khi chạy vòng lặp, nhưng tôi không chắc chắn làm thế nào để làm điều này?

+7

Bạn nên đăng một số mã để làm cho điều này rõ ràng hơn một chút (không có ý định chơi chữ). – user973572

+0

Ví dụ được thêm vào OP –

+0

Bản sao có thể có của [Thuật toán tốt nhất cho bit đảo ngược (từ MSB-> LSB sang LSB-> MSB) trong C] (http://stackoverflow.com/questions/746171/best-algorithm-for-bit -reversal-from-msb-lsb-to-lsb-msb-in-c) –

Trả lời

18

Đảo ngược các bit trong một từ khó chịu và dễ dàng hơn chỉ để xuất chúng theo thứ tự ngược lại. Ví dụ:

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

Đây là giải pháp điển hình để đảo ngược thứ tự bit:

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

Bạn có thể vui lòng cho tôi giải thích thêm về phần thứ hai (hoặc cho tôi một cụm từ để đưa vào google). Điều đó không có ý nghĩa đối với tôi và kiến ​​thức của tôi về biểu diễn bit là tồi tệ hơn tôi nghĩ. Cảm ơn bạn trước. – AoeAoe

+1

@AoeAoe: Đó là một chút khó khăn hack. Tôi đề nghị viết ra các số trong nhị phân nếu bạn muốn hiểu nó hoạt động như thế nào. Mỗi dòng trao đổi vị trí của một nửa số bit với một nửa khác và năm dòng trong lõi có thể được viết theo thứ tự bất kỳ. –

+2

Dưới đây là giải thích: Chúng ta hãy chia tất cả các bit theo kích thước khối b, bắt đầu với b = 1. Bây giờ chúng tôi trao đổi mỗi khối liền kề. Kích thước khối đôi và lặp lại. Tiếp tục cho đến khi kích thước khối bằng một nửa kích thước từ. Đối với 32 bit, đây sẽ là 5 bước. Mỗi bước có thể được viết là ((x & mask) << b) | ((x & mặt nạ ') << b). Như vậy trong 5 câu lệnh, chúng ta có thể đảo ngược 32 bit int. – ShitalShah

2

bạn có thể di chuyển từ trái sang phải thay vào đó, đó là chuyển một từ MSB đến LSB, ví dụ:

unsigned n = 20543; 
unsigned x = 1<<31; 
while (x) { 
    printf("%u ", (x&n)!=0); 
    x = x>>1; 
} 
+0

@SethCarnegie no, đó là x >> 1 vì x = 1 << 31 vì vậy chúng ta đang chuyển từ MSB sang LSB hoặc sang trái sang phải để đảo ngược thứ tự của các bit. – iabdalkader

+0

Ah Tôi đã nhầm lẫn 'x' với' n'. –

1

bạn có thể đảo ngược các bit như bạn xuất chúng, và thay vào đó lưu trữ chúng trong số nguyên khác, và làm điều đó một lần nữa:

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

Hoặc bạn chỉ có thể làm ngược lại, chuyển mặt nạ của bạn:

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

Nếu bạn muốn loại bỏ số 0 đầu của bạn có thể đợi cho một 1 để in, hoặc làm một đi qua sơ bộ:

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

cách này bạn sẽ đặt mặt nạ trên 1 đầu tiên được in và quên đi số 0 đầu của

Nhưng hãy nhớ rằng: in giá trị nhị phân của một số nguyên có thể được thực hiện chỉ với printf

+0

Chỉ cần nhớ nhân kích thước của 8, và giải pháp đầu tiên của bạn sẽ được sử dụng tốt. (Thứ hai sẽ tràn, nhưng với một số sửa chữa, nó có thể hoạt động) – asaelr

+2

Vẫn còn tốt hơn, nhân với 'CHAR_BIT'. –

+0

Làm cách nào để loại bỏ 0s đầu ra khỏi đầu ra trong trường hợp này? Tôi có thể kiểm tra và không đầu ra cho đến khi nó phát hiện ra một bit thực, nhưng điều đó không có vẻ rất thanh lịch và cũng sẽ không hoạt động nếu đầu vào cho chương trình là 0. –

2

Bạn chỉ có thể lặp qua các bit từ đầu lớn đến cuối.

#define N_BITS (sizeof(unsigned) * CHAR_BIT) 
#define HI_BIT (1 << (N_BITS - 1)) 

for (int i = 0; i < N_BITS; i++) { 
    printf("%d", !!(x & HI_BIT)); 
    x <<= 1; 
} 

đâu !! cũng có thể được viết !=0 hoặc >> (N_BITS - 1).

+0

Không phải !! (x) == x? đôi negation hủy bỏ ra, và == 0 sẽ là đúng, tức là 1 nếu nó 0 để nó in các bit lộn. – iabdalkader

+0

@mux: không, đôi phủ định chỉ hủy bỏ cho 0 và 1. Bạn đang đúng về '== 0', mà nên có được'! = 0', xin lỗi. –

+0

oh Tôi thấy nó bây giờ, một cái gì đó như thế! (! (512)) =! (0) = 1 cảm ơn, tôi đổ lỗi cho nó quá nhiều rời rạc :) ... – iabdalkader

1
unsigned int rev_bits(unsigned int input) 
{ 
    unsigned int output = 0; 
    unsigned int n = sizeof(input) << 3; 
    unsigned int i = 0; 

    for (i = 0; i < n; i++) 
     if ((input >> i) & 0x1) 
      output |= (0x1 << (n - 1 - i)); 

    return output; 
} 
0

Tôi đã đưa ra giải pháp không liên quan đến bất kỳ ứng dụng nào của nhà điều hành bitwise. nó không hiệu quả về mặt không gian và thời gian.

int arr[32]; 
for(int i=0;i<32;i++) 
{ 
    arr[i]=A%2; 
    A=A/2; 
} 
double res=1; 
double re=0; 
for(int i=0;i<32;i++) 
{ 
    int j=31-i; 
    res=arr[i]; 
    while(j>0) 
    { 
     res=res*2; 
     j--; 
    } 
    re=re+res; 
} 
cout<<(unsigned int)re; 
0

Đây là phiên bản golang của các bit đảo ngược trong một số nguyên, nếu có ai đang tìm kiếm một. Tôi đã viết điều này với một cách tiếp cận tương tự như chuỗi đảo ngược trong c. Đi qua từ bit 0 đến 15 (31/2), hoán đổi bit i với bit (31-i). Vui lòng kiểm tra mã sau đây.

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

Bạn có thể đảo ngược unsigned 32-bit integer và trở về bằng cách sử dụng chức năng reverse sau:

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

Nhớ rằng phải có thư viện toán học. Happy coding :)

0

Tôi tin rằng câu hỏi đặt ra là làm thế nào để không phải là đầu ra theo thứ tự ngược lại.

câu trả lời

Fun (đệ quy):

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

sản lượng dự kiến:

10=1010 
49=110001 
498598=1111001101110100110 

phiên bản tuần tự (chọn off the-bit cao đầu tiên):

#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"); 
    }  
} 
Các vấn đề liên quan