我正在将一个数字转换为二进制,并需要使用putchar
输出每个数字。
问题是我得到的顺序是相反的。
有没有办法在对其进行操作之前反转数字的位模式?
例如,int n具有特定的位模式 - 如何反转这个位模式?
我正在将一个数字转换为二进制,并需要使用putchar
输出每个数字。
问题是我得到的顺序是相反的。
有没有办法在对其进行操作之前反转数字的位模式?
例如,int n具有特定的位模式 - 如何反转这个位模式?
有很多方法可以做到这一点,其中一些非常快速。我不得不查找资料。
反转字节中的位
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]];
将输入的位弹出并推到输出中。乘以2和除以2都是推和弹出操作。伪代码如下:
reverse_bits(x) {
total = 0
repeat n times {
total = total * 2
total += x % 2 // modulo operation
x = x / 2
}
return total
}
如果你还没有见过取模运算符,请参考维基百科的modulo operation页面。
进一步的要点:
<<
、>>
、&
)来代替除法和取模?这会使它更快吗?x % 2
等价于 x & 1
。 - Dave Jarvisx ^= x;
可能实际上会更慢,因为一些芯片设计者(例如 Intel)习惯于将 x = 0
的汇编指令重新排列到比对应的异或操作更高的位置,以加快速度。 - dirkgentlyunsigned int n = 12345; //Source
unsigned int m = 0; //Destination
int i;
for(i=0;i<32;i++)
{
m |= n&1;
m <<= 1;
n >>= 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以相反的顺序将该位恢复到另一个寄存器中。
这里是我用来反转字节和四元组中的位的函数。
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) );
}
我猜你有一个整数,尝试将其转换为二进制?
"答案"是ABCDEFG,但你的"答案"是GFEDCBA?
如果是这样,我建议你仔细检查正在使用的计算机的字节序和"答案"所来自的计算机的字节序。