[算法]有趣的《Bit Twiddling Hacks》字节位反转

本文深入探讨了两种高效的字节位反转算法,分别通过乘法、与运算和取模,以及乘法、与运算、乘法和右移位实现。详细解释了每一步操作如何作用于输入的字节,利用位操作的特性实现位反转,并通过实例展示了这些操作如何组合以达到预期效果。这些算法对于理解和优化位操作的代码具有重要价值。
摘要由CSDN通过智能技术生成

[算法]有趣的《Bit Twiddling Hacks》字节位反转

给定一个字节input,定义其二进制为abcd efgh,将其比特位进行反转。

1. 乘+与+取模

公式:
r e v e r t e d = ( i n p u t   ∗   0 x 0202020202 U L L   &   0 x 010884422010 U L L )   %   1023 reverted = (input \ * \ 0x0202020202ULL \ \& \ 0x010884422010ULL) \ \% \ 1023 reverted=(input  0x0202020202ULL & 0x010884422010ULL) % 1023

input的二进制abcd efgh代入展开如下:

                                              abcd efgh (-> hgfe dcba)
*            10 0000 0010 0000 0010 0000 0010 0000 0010 (0x0202020202)
-------------------------------------------------------
    a bcde fgha bcde fgha bcde fgha bcde fgha bcde fgh0
&   1 0000 1000 1000 0100 0100 0010 0010 0000 0001 0000 (0x010884422010)
-------------------------------------------------------
    a 0000 f000 b000 0g00 0c00 00h0 00d0 0000 000e 0000
%                                             1111 1111 (1023)
-------------------------------------------------------
                                           00 000e 0000
                                           00 h000 d000
                                           00 0g00 0c00
                                           00 00f0 00b0
                                           00 0000 000a
-------------------------------------------------------
                                              hgfe dcba

1.1 第一步:input * 0x0202020202ULL

abcd efgh复制5份,并依次铺开在不同位置。得到000a bcde fgha bcde fgha bcde fgha bcde fgha bcde fgh0

1.2 第二步:第一步结果 & 0x010884422010ULL

a bcde fgha bcde fgha bcde fgha bcde fgha bcde fgh0分为10bit一组为 000000000a bcdefghabc defghabcde fghabcdefg habcdefgh0

找出各组从第1位到第8位以次对应abcdefgh的位置:

000000000a bcdefghabc defghabcde fghabcdefg habcdefgh0
         1     6   2     8   3     7   4         5    
------------------------------------------------------
0000000001 0000100010 0001000100 0010001000 0000010000

0000000001 0000100010 0001000100 0010001000 0000010000即为0x010884422010ULL,通过&运算就将abcdefgh各bit分离出来了。

1.3 第三部:第二步结果 % 1023

首先,了解两个公式:

  1. x n ≡ 1 ( m o d   x − 1 ) x^n ≡ 1 (mod\ x-1) xn1(mod x1)

    比如100 ≡ 1 (mod 9),1000 ≡ 1 (mod 9)。

  2. y ≡ s u m ( a ∗ x n ) ≡ s u m ( a ) ( m o d   x − 1 ) y ≡ sum(a*x^n) ≡ sum (a) (mod\ x-1) ysum(axn)sum(a)(mod x1)。(sum:求和)

    比如300 ≡ (100 + 200) ≡ 1 + 2 (mod 9) ≡ 3 (mod 9)。

所以对1023取模,可以这样理解:

y ≡ 0000000000a 0000f000b0 000g000c00 00h000d000 00000e0000 
  ≡ a*x^4 + 0000f000b0*x^3 + 000g000c00*x^2 + 00h000d000*x +00000e0000 
  ≡ a + 0000f000b0 + 000g000c00 + 00h000d000 + 00000e0000 (mod x - 1)000000000a
   + 0000f000b0 
   + 000g000c00 
   + 00h000d000 
   + 00000e0000 (mod x - 1)00hgfedcba (mod x - 1) 

其中x为1024,即 2 10 2^{10} 210,所以x-1即为1023。通过对1023取模,将第二步按照10bit分组出来的数刚好得到了000000000a、0000f000b0、000g000c00、00h000d000、00000e0000五个数,五个分数相加,刚好等效于位或的效果!

2. 乘+与+乘+移位

公式:
r e v e r t e d = ( ( i n p u t   ∗   0 x 80200802 U L L )   &   0 x 0884422110 U L L )   ∗   0 x 0101010101 U L L > > 32 reverted = ((input\ * \ 0x80200802ULL)\ \& \ 0x0884422110ULL) \ *\ 0x0101010101ULL >> 32 reverted=((input  0x80200802ULL) & 0x0884422110ULL)  0x0101010101ULL>>32
原理看这里:Reverse the bits in a byte with 4 operations (64-bit multiply, no division):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值