将一个字节里的比特头尾翻转
2010-01-19 03:55
148 查看
Reverse bits the obvious way
unsigned int v; // input bits to be reversed unsigned int r = v; // r will be reversed bits of v; first get LSB of v int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end for (v >>= 1; v; v >>= 1) { r <<= 1; r |= v & 1; s--; } r <<= s; // shift when v's highest bits are zero
On October 15, 2004, Michael Hoisie pointed out a bug in the original version.
Randal E. Bryant suggested removing an extra operation on May 3, 2005.
Behdad Esfabod suggested a slight change that eliminated one iteration of the
loop on May 18, 2005. Then, on February 6, 2007, Liyong Zhou suggested a
better version that loops while v is not 0, so rather than iterating over
all bits it stops early.
Reverse bits in word by lookup table
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]];
The first method takes about 17 operations, and the second takes about 12,
assuming your CPU can load and store bytes easily.
On July 14, 2009 Hallvard Furuseth suggested the macro compacted table.
Reverse the bits in a byte with 3 operations (64-bit multiply and modulus division):
unsigned char b; // reverse this (8-bit) byte b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
The multiply operation creates five separate copies of the 8-bit
byte pattern to fan-out into a 64-bit value.
The AND operation selects the bits that are in the correct (reversed)
positions, relative to each 10-bit groups of bits.
The multiply and the AND operations copy the bits from the original
byte so they each appear in only one of the 10-bit sets.
The reversed positions of the bits from the original byte coincide with
their relative positions within any 10-bit set.
The last step, which involves modulus division by 2^10 - 1, has the
effect of merging together each set of 10 bits
(from positions 0-9, 10-19, 20-29, ...) in the 64-bit value.
They do not overlap, so the addition steps underlying the
modulus division behave like or operations.
This method was attributed to Rich Schroeppel in the
Programming Hacks section of
Beeler, M., Gosper, R. W., and Schroeppel, R.
HAKMEM. MIT AI Memo 239, Feb. 29, 1972.
Reverse the bits in a byte with 4 operations (64-bit multiply, no division):
unsigned char b; // reverse this byte b = ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
The following shows the flow of the bit values with the boolean variables
a, b, c, d, e, f, g,
and
h
, which
comprise an 8-bit byte. Notice how the first multiply fans out the
bit pattern to multiple copies, while the last multiply combines them
in the fifth byte from the right.
abcd efgh (-> hgfe dcba) * 1000 0000 0010 0000 0000 1000 0000 0010 (0x80200802) ------------------------------------------------------------------------------------------------- 0abc defg h00a bcde fgh0 0abc defg h00a bcde fgh0 & 0000 1000 1000 0100 0100 0010 0010 0001 0001 0000 (0x0884422110) ------------------------------------------------------------------------------------------------- 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 * 0000 0001 0000 0001 0000 0001 0000 0001 0000 0001 (0x0101010101) ------------------------------------------------------------------------------------------------- 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 0000 d000 h000 0c00 0g00 00b0 00f0 000a 000e 0000 ------------------------------------------------------------------------------------------------- 0000 d000 h000 dc00 hg00 dcb0 hgf0 dcba hgfe dcba hgfe 0cba 0gfe 00ba 00fe 000a 000e 0000 >> 32 ------------------------------------------------------------------------------------------------- 0000 d000 h000 dc00 hg00 dcb0 hgf0 dcba hgfe dcba & 1111 1111 ------------------------------------------------------------------------------------------------- hgfe dcba
Note that the last two steps can be combined on some processors because
the registers can be accessed as bytes;
just multiply so that a register stores the upper 32 bits of the result
and the take the low byte. Thus, it may take only 6 operations.
Devised by Sean Anderson, July 13, 2001.
Reverse the bits in a byte with 7 operations (no 64-bit):
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
Make sure you assign or cast the result to an unsigned char to remove
garbage in the higher bits.
Devised by Sean Anderson, July 13, 2001. Typo spotted and correction supplied
by Mike Keith, January 3, 2002.
相关文章推荐
- matlab 对一个向量实施比特翻转操作的函数bitrevorder()
- 为什么一个字节等于8个比特
- 怎么把一个字节里的比特顺序倒转?
- 8位字节的比特翻转
- Oracle一个中文汉字占用几个字节
- 有关于【该文件的字符编码需要在传输协议层声明,或者在文件中加入一个 BOM(字节顺序标记)】的另一种解决办法
- 【Java】实现一个递归和非递归的reverse,它们能把一个表翻转过来。
- listview一个item只能显示255个字节的数据
- byte字节,方便记忆可以记为【百特】与bit位【比特】
- C# 设置和获取一个字节的某一位的值的方法 .
- java中一个汉字和一个字母所占内存字节比较以及后台验证的减半处理
- 将一个字节转化成十六进制形式的字符串
- 一个字符占多少个字节
- 字节码实战--手写一个btrace
- 请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量)。 给定一个string iniString,请返回一个string,为翻转后的字符串。保证字符串的
- 关于C中为何一个字节表示有符号数范围是[-128-127]
- 常见面试题——计算一个字节里有多少bit置1
- 一个int类型究竟占多少个字节
- 【Java】编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
- 一个页面中用Get方法到底可以发送多少字节的数据呢?