Get specific bit from uint32

后端 未结 1 1532
离开以前
离开以前 2021-01-18 14:57

I have a UInt32 variable like 3238844000.

Now I want to get the first two bits of this number and the 6 bits after the first two bits. Both bits should

相关标签:
1条回答
  • 2021-01-18 15:23

    Update 2:

    The simplest (and also the fastest) way for this case turns out to be by purely using the bitwise-shift operators

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

    I have heard before that bitwise-shift operations tend to be faster. But today, out of curiosity*, I really compared the performance between bitwise-shift + mask ((int)((input & mask2) >> 24)) with bitwise-shift alone ((int)((input << 2) >> 26)). bitwise-shift alone operation is approximately faster by 10%-15%.

    This is the result I got:

    [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
    

    Note: each experiment is done for (5,000,000 x 100) operations.

    *remembering my old days dealing with micro-controllers... ;)


    Original:

    Just like how you find binary representation for your UInt32, you should find the right bitwise mask in its binary representation too:

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

    And then use them with bitwise-and operator

    To get the first two bits, you could simply use the mask like this:

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

    And to get the next 6 bits:

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

    If you need them in int, then simply cast them:

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

    And if you want to put the results in the LSB (the least significant byte, the rightmost 8-bit in this case), use bitwise right shift operator:

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

    Update:

    As for the above shifted version, actually, you could also simply bitwise right shift the first one and do almost similarly for the second, except that it would require a bitwise mask of 0x3F (0011 1111) to clear up the unwanted first two bits.

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

    What happen to them in the bit-representation is as follow (I give comments to ease following the logical flow):

    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
    

    Thus you will get 3 (0000 0000 0000 0000 0000 0000 0000 0011) for your first value, and get 1 (0000 0000 0000 0000 0000 0000 0000 0001) for your second value.

    Along with following the example above, I think you can get the idea on how to do this on many other different cases too.

    0 讨论(0)
提交回复
热议问题