C中的反转位模式

时间:2010-02-12 16:10:23

标签: c

我正在将数字转换为二进制数,并且必须使用putchar输出每个数字。

问题是我正在接受订单。

在做自己的后缀之前,有没有反转数字位模式?

因为在int中有一个特定的位模式 - 我该如何反转这个位模式?

6 个答案:

答案 0 :(得分:9)

有很多方法可以做到这一点,有些方法非常快。我不得不查一查。

字节中的反转位

b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 

在5 * lg(N)操作中并行反转N位数量:

unsigned int v; // 32-bit word to reverse bit order

// swap odd and even bits
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// swap nibbles ... 
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = ( v >> 16             ) | ( v               << 16);

查找表中的单词反转位

static const unsigned char BitReverseTable256[256] = 
{
#   define R2(n)     n,     n + 2*64,     n + 1*64,     n + 3*64
#   define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16)
#   define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 )
    R6(0), R6(2), R6(1), R6(3)
};

unsigned int v; // reverse 32-bit value, 8 bits at time
unsigned int c; // c will get v reversed

// Option 1:
c = (BitReverseTable256[v & 0xff] << 24) | 
    (BitReverseTable256[(v >> 8) & 0xff] << 16) | 
    (BitReverseTable256[(v >> 16) & 0xff] << 8) |
    (BitReverseTable256[(v >> 24) & 0xff]);

// Option 2:
unsigned char * p = (unsigned char *) &v;
unsigned char * q = (unsigned char *) &c;
q[3] = BitReverseTable256[p[0]]; 
q[2] = BitReverseTable256[p[1]]; 
q[1] = BitReverseTable256[p[2]]; 
q[0] = BitReverseTable256[p[3]];

请查看http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel以获取更多信息和参考资料。

答案 1 :(得分:5)

关闭输入并将它们推到输出上。乘法和除以2是推送和弹出操作。在伪代码中:

reverse_bits(x) {
    total = 0
    repeat n times {
       total = total * 2
       total += x % 2 // modulo operation
       x = x / 2
    }
    return total
}

如果您还没有看过此运营商,请参阅维基百科上的modulo operation

进一步的观点:

  • 如果你改变2到4会怎么样?还是10?
  • 这对n的价值有何影响?什么是n?
  • 你怎么能使用按位运算符(<<>>&)而不是除法和模数?这会让它更快吗?
  • 我们可以使用不同的算法来加快速度吗?查找表有帮助吗?

答案 2 :(得分:2)

让我猜一下:你有一个循环打印第0位(n&amp; 1),然后右移数字。相反,写一个打印第31位(n&amp; 0x80000000)并将数字左移的循环。在执行该循环之前,执行另一个循环,将数字向左移动,直到第31位为1;除非你这样做,否则你会得到前导零。

也可以进行逆转。像这样的事情:

unsigned int n = 12345; //Source
unsigned int m = 0; //Destination
int i;
for(i=0;i<32;i++)
{
    m |= n&1;
    m <<= 1;
    n >>= 1;
}

答案 3 :(得分:1)

我知道:这不完全是C,但我认为这是一个有趣的答案:

int reverse(int i) {
  int output;
  __asm__(
     "nextbit:"
        "rcll $1, %%eax;"
        "rcrl $1, %%ebx;"
        "loop nextbit;"
        : "=b" (output)
        : "a" (i), "c" (sizeof(i)*8) );
  return output;
}

rcl操作码将移出的位置于进位标志中,然后rcr以相反的顺序将该位恢复到另一个寄存器。

答案 4 :(得分:0)

我的猜测是你有一个整数而你正在尝试将其转换为二进制文件?

“答案”是ABCDEFG,但你的“回答”是GFEDCBA?

如果是这样的话,我会仔细检查你正在进行的机器的端部和机器的“答案”来自。

答案 5 :(得分:0)

以下是我用来反转字节中的位和反转字节中的字节的函数。

inline unsigned char reverse(unsigned char b) {
    return (b&1 << 7)
         | (b&2 << 5)
         | (b&4 << 3)
         | (b&8 << 1)
         | (b&0x10 >> 1)
         | (b&0x20 >> 3)
         | (b&0x40 >> 5)
         | (b&0x80 >> 7);
}

inline unsigned long wreverse(unsigned long w) {
    return ( ( w     &0xFF) << 24)
         | ( ((w>>8) &0xFF) << 16)
         | ( ((w>>16)&0xFF) << 8)
         | ( ((w>>24)&0xFF) );
}