简体   繁体   中英

How to get the number represented by least-significant non-zero bit efficiently

For example, if it is 0xc0, then the result is 0x40, Since 0xc0 is equal to binary 11000000, the result should be 01000000.

public static byte Puzzle(byte x) {
    byte result = 0;
    byte[] masks = new byte[]{1,2,4,8,16,32,64,128};
    foreach(var mask in masks)
    {
      if((x&mask)!=0)
      {
        return mask;
      }
    }
    return 0;
}

This is my current solution. It turns out this question can be solved in 3-4 lines...

public static byte Puzzle(byte x) {
    return (byte) (x & (~x ^ -x));
}    

if x is bbbb1000, ~x is BBBB0111 (B is !b)

-x is really ~x+1, (2's complement) so adding 1 to BBBB0111 is BBBB1000

~x ^ -x then is 00001111 & with x gives the lowest 1 bit.

A better answer was supplied by harold in the comments

public static byte Puzzle(byte x) {
    return (byte) (x & -x);
}    

Maby not the best solution, but you can prepare an array byte[256], store the result for each number and then use it.

Another solution in 1 line:

return (byte)((~(x | (x << 1) | (x << 2) | (x << 3) | (x << 4) | (x << 5) | (x << 6) | (x << 7) | (x << 8)) + 1) >> 1);

Hardly a 1-line solution, but at least it doesn't use the hardcoded list of the bits.

I'd do it with some simple bit shifting. Basically, down-shifting the value until the lowest bit is not 0, and then upshifting 1 with the amount of performed shifts to reconstruct the least significant value. Since it's a 'while' it needs an advance zero check though, or it'll go into an infinite loop on zero.

public static Byte Puzzle(Byte x)
{
    if (x == 0)
        return 0;
    byte shifts = 0;
    while ((x & 1) == 0)
    {
        shifts++;
        x = (Byte)(x >> 1);
    }
    return (Byte)(1 << shifts);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM