web-dev-qa-db-ja.com

符号なし整数のCリバースビット

ビット単位の演算子を使用して符号なし整数を2進数に変換しています。現在、整数と1を実行してビットが1か0かを確認して出力し、次に1ずつ右シフトして2で除算します。逆)なので、始める前に整数のビット順序を逆にすることを考えました。

これを行う簡単な方法はありますか?

例:したがって、unsigned int 10 = 1010が与えられた場合

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

これは間違った0101を返します...ループを実行する前に元々ビットの順序を逆にすることを考えていましたが、これを行う方法がわかりませんか?

10
user1139103

Wordのビットを逆にするのは面倒で、逆の順序で出力する方が簡単です。例えば。、

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

ビット順序を逆にする一般的な解決策は次のとおりです。

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;
}
20
Dietrich Epp

代わりに、左から右に移動できます。つまり、MSBからLSBに1つシフトします。次に例を示します。

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

ビッグエンドからリトルエンドまでビットをループすることができます。

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

ここで、_!!_は_!=0_または>> (N_BITS - 1)と書くこともできます。

2
Fred Foo
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;
}
1
user1596193

出力するようにビットを逆にして、代わりに別の整数に格納して、もう一度実行することができます。

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

または、反対のことをして、マスクをシフトすることもできます:

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

先頭の0を削除する場合は、1が出力されるのを待つか、予備的な確認を行うことができます。

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

このようにして、印刷する最初の1にマスクを配置し、先頭の0を忘れます。

ただし、整数のバイナリ値の出力はprintfだけで実行できることを忘れないでください。

1
Eregrith

整数のビットを反転する最良の方法は次のとおりです。

  1. それは非常に効率的です。
  2. 左端のビットが1の場合にのみ実行されます。

コードスニペット

int reverse ( unsigned int n )
{
    int x = 0;
    int mask = 1;
    while ( n > 0 )
    {
        x = x << 1;
        if ( mask & n )
            x = x | 1;
        n = n >> 1;
    }
    return x;
}
1
Praveen Kumar

質問は、逆の順序でnot出力する方法を尋ねていると思います。

楽しい答え(再帰):

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

期待される出力:

10=1010
49=110001
498598=1111001101110100110

シーケンシャルバージョン(最初に上位ビットを選択):

#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
Persixty

私は、ビット演算子の適用を一切含まないソリューションを思いつきました。空間と時間の両方の点で非効率的です。

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
rajat jain

誰かが探しているなら、これは整数の逆ビットのgolangバージョンです。私はこれをcの文字列逆に似たアプローチで書きました。ビット0から15(31/2)に移動し、ビットiをビット(31-i)と交換します。以下のコードを確認してください。

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
Gaurav Sinha

次のreverse関数を使用して、unsigned 32-bit integerを逆にして戻ることができます。

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

数学ライブラリを含めることを忘れないでください。ハッピーコーディング:)

0
Prateek Oraon

Dietrich Eppによる2番目の回答は、高速キャッシュを備えた最新のプロセッサで最適なものである可能性があります。ただし、一般的なマイクロコントローラーではそうではなく、以下ははるかに高速であるだけでなく、より用途が広く、よりコンパクトです(C)。

// reverse a byte
uint8_t reverse_u8(uint8_t x)
{
   const unsigned char * rev = "\x0\x8\x4\xC\x2\xA\x6\xE\x1\x9\x5\xD\x3\xB\x7\xF";
   return rev[(x & 0xF0) >> 4] | (rev[x & 0x0F] << 4);
}

// reverse a Word
uint16_t reverse_u16(uint16_t x)
{
   return reverse_u8(x >> 8) | (reverse_u8(x & 0xFF) << 8);
}

// reverse a long
uint32_t reverse_u32(uint32_t x)
{
   return reverse_u16(x >> 16) | (reverse_u16(x & 0xFFFF) << 16);
}

コードはJava、Go、Rustなどに簡単に変換できます。もちろん、数字だけを印刷する必要がある場合は、逆の順序で印刷するのが最善です(Dietrich Eppの回答を参照)。 。

0
user103185