【问题标题】:Get specific bit from uint32从 uint32 获取特定位
【发布时间】:2016-01-18 08:00:31
【问题描述】:

我有一个 UInt32 变量,例如 3238844000。

现在我想得到这个数字的前两位和前两位之后的 6 位。两个位都应该是 int。

Decimal: 3238844000
Binary:  11000001000011001101011001100000
         ^^

Decimal: 3238844000
Binary:  11000001000011001101011001100000
           ^^^^^^ 

【问题讨论】:

    标签: c# .net bit-manipulation bitmask


    【解决方案1】:

    更新 2:

    这种情况的最简单(也是最快)的方式是纯粹使用bitwise-shift运营商

    int val = (int)(input >> 30); // performs the same 
    int val2 = (int)((input << 2) >> 26); //the simplest and the fastest way
    

    我之前听说按位移位操作往往更快。但是今天,出于好奇*,我真的比较了按位移位 + 掩码 ((int)((input &amp; mask2) &gt;&gt; 24)) 与单独按位移位 ((int)((input &lt;&lt; 2) &gt;&gt; 26)) 之间的性能。仅按位移位操作大约快 10%-15%

    这是我得到的结果:

    [2016-01-20 04:01:26.638 UTC] shift-mask: 235 ms    shift-only: 199 ms
    [2016-01-20 04:01:30.402 UTC] shift-mask: 233 ms    shift-only: 200 ms
    [2016-01-20 04:01:31.265 UTC] shift-mask: 233 ms    shift-only: 198 ms
    [2016-01-20 04:01:32.116 UTC] shift-mask: 227 ms    shift-only: 199 ms
    [2016-01-20 04:01:32.850 UTC] shift-mask: 233 ms    shift-only: 198 ms
    [2016-01-20 04:01:33.584 UTC] shift-mask: 230 ms    shift-only: 199 ms
    [2016-01-20 04:01:34.280 UTC] shift-mask: 263 ms    shift-only: 214 ms
    [2016-01-20 04:01:35.055 UTC] shift-mask: 229 ms    shift-only: 201 ms
    [2016-01-20 04:01:36.996 UTC] shift-mask: 234 ms    shift-only: 201 ms
    [2016-01-20 04:01:37.933 UTC] shift-mask: 224 ms    shift-only: 198 ms
    [2016-01-20 04:01:38.353 UTC] shift-mask: 222 ms    shift-only: 196 ms
    [2016-01-20 04:01:38.798 UTC] shift-mask: 233 ms    shift-only: 211 ms
    [2016-01-20 04:01:39.246 UTC] shift-mask: 235 ms    shift-only: 213 ms
    [2016-01-20 04:01:39.668 UTC] shift-mask: 223 ms    shift-only: 198 ms
    [2016-01-20 04:01:41.102 UTC] shift-mask: 234 ms    shift-only: 200 ms
    [2016-01-20 04:01:41.524 UTC] shift-mask: 224 ms    shift-only: 198 ms
    [2016-01-20 04:01:41.948 UTC] shift-mask: 223 ms    shift-only: 200 ms
    [2016-01-20 04:01:42.373 UTC] shift-mask: 224 ms    shift-only: 200 ms
    [2016-01-20 04:01:43.521 UTC] shift-mask: 233 ms    shift-only: 197 ms
    [2016-01-20 04:01:44.272 UTC] shift-mask: 237 ms    shift-only: 216 ms
    [2016-01-20 04:01:44.909 UTC] shift-mask: 231 ms    shift-only: 196 ms
    [2016-01-20 04:01:45.353 UTC] shift-mask: 230 ms    shift-only: 213 ms
    [2016-01-20 04:01:45.850 UTC] shift-mask: 237 ms    shift-only: 207 ms
    [2016-01-20 04:01:46.276 UTC] shift-mask: 226 ms    shift-only: 200 ms
    [2016-01-20 04:01:47.074 UTC] shift-mask: 234 ms    shift-only: 203 ms
    [2016-01-20 04:01:47.718 UTC] shift-mask: 230 ms    shift-only: 199 ms
    [2016-01-20 04:01:48.144 UTC] shift-mask: 226 ms    shift-only: 200 ms
    [2016-01-20 04:01:48.567 UTC] shift-mask: 225 ms    shift-only: 198 ms
    [2016-01-20 04:01:48.994 UTC] shift-mask: 225 ms    shift-only: 199 ms
    [2016-01-20 04:01:49.429 UTC] shift-mask: 223 ms    shift-only: 211 ms
    [2016-01-20 04:01:49.860 UTC] shift-mask: 232 ms    shift-only: 198 ms
    [2016-01-20 04:01:50.284 UTC] shift-mask: 225 ms    shift-only: 199 ms
    

    注意:每个实验都是针对 (5,000,000 x 100) 次操作完成的。

    *回忆我过去与微控制器打交道的日子... ;)


    原文:

    就像为UInt32 找到二进制表示一样,您也应该在其二进制表示中找到正确的位掩码

    uint mask1 = 0xC0000000; //1100 0000 0000 0000 0000 0000 0000 0000
    uint mask2 = 0x3F000000; //0011 1111 0000 0000 0000 0000 0000 0000 
    

    然后将它们与 bitwise-and 运算符一起使用

    要获取前两位,您可以像这样简单地使用掩码:

    uint val = input & mask1; //should give you the first two bits, the rests are zero
    

    并获取接下来的 6 位:

    uint val2 = input & mask2; //similarly, should give you only the six bits in the position which you want
    

    如果您在int 中需要它们,则只需投射它们:

    int val = (int)(input & mask1);
    int val2 = (int)(input & mask2);
    

    如果你想把结果放在 LSB(最不重要的byte,在这种情况下是最右边的8-bit),使用按位右移运算符:

    int val = (int)((input & mask1) >> 30); //30 bits are 0
    int val2 = (int)((input & mask2) >> 24); //24 bits are 0
    

    更新:

    至于上面的移位版本,实际上,您也可以简单地按位右移第一个,第二个几乎类似,除了它需要一个按位掩码 of 0x3F (0011 1111) 清除不需要的前两位。

    int val = (int)(input >> 30); // performs the same 
    int val2 = (int)((input >> 24) & 0x3F); //the simpler way
    

    它们在位表示中发生的情况如下(我给 cmets 以简化逻辑流程):

    The first one:
    
    1100 0001 0000 1100 1101 0110 0110 0000
    --------------------------------------- >> 30 //bitwise right shift by 30
    0000 0000 0000 0000 0000 0000 0000 0011 //you get only the first two bits, the rests are all replaced by 0
    
    The second one:
    
    1100 0001 0000 1100 1101 0110 0110 0000
    --------------------------------------- >> 24 //bitwise right shift by 24
    0000 0000 0000 0000 0000 0000 1100 0001
                                  0011 1111 //this is 0x3f
    --------------------------------------- & //this is bitwise-and
    0000 0000 0000 0000 0000 0000 0000 0001 //you only get the 6 bits which you want
    

    因此,您将获得3 (0000 0000 0000 0000 0000 0000 0000 0011) 作为您的第一个值,并获得1 (0000 0000 0000 0000 0000 0000 0000 0001) 作为您的第二个值。

    除了按照上面的示例,我认为您也可以了解如何在许多其他不同情况下执行此操作。

    【讨论】:

    • 对于移位版本,移位后最好掩蔽。更容易找出面具。
    • 感谢您的精彩回答
    • @Philies 没问题。 ;) 很高兴我能提供任何帮助。在我以前处理微控制器的 C 代码时,曾经经常处理位移。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-01
    • 2018-06-26
    • 1970-01-01
    • 2014-04-14
    • 2015-02-28
    • 1970-01-01
    相关资源
    最近更新 更多