简体   繁体   中英

How to count trailing zeros in a binary representation of an integer number with C#

How to count efficiently the number of trailing zeros in a binary representation of an integer number?

Here's a nice, quick and easy implementation:

public static int NumberOfTrailingZeros(int i)
{
    return _lookup[(i & -i) % 37];
}

private static readonly int[] _lookup =
    {
        32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17,
        0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18
    };

(Taken from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup .)

Just make a mask starting at the first digit and keep moving it over until it finds something:

public static int numTrailingBinaryZeros(int n)
{
    int mask = 1;
    for (int i = 0; i < 32; i++, mask <<= 1)
        if ((n & mask) != 0)
            return i;

    return 32;
}

In java it is implemented like:

 public static int numberOfTrailingZeros(int i) { // HD, Figure 5-14 int y; if (i == 0) return 32; int n = 31; y = i <<16; if (y != 0) { n = n -16; i = y; } y = i << 8; if (y != 0) { n = n - 8; i = y; } y = i << 4; if (y != 0) { n = n - 4; i = y; } y = i << 2; if (y != 0) { n = n - 2; i = y; } return n - ((i << 1) >>> 31); }

I think idea is from "Hacker's Delight"

int trailingZeros(int n) {
    if(!n)
        return 32;

    for(int s = 0; !(n & 1); s++)
        n >>= 1;
    return s;
}

This variation on the Java version uses a bit more bit twiddling to remove the last conditional test:

    public static uint Ctz(uint num)
    {
        if (num == 0) return 32;    // optional, otherwise returns 0

        uint tmp;
        uint res = 0;
        num &= (uint)-(int)num;  // Isolate bit
        tmp = num >> 16; if (tmp != 0) { num = tmp; res += 16; }
        tmp = num >> 8;  if (tmp != 0) { num = tmp; res += 8; }
        tmp = num >> 4;  if (tmp != 0) { num = tmp; res += 4; }
        return res + ((num >> 1) - (num >> 3));
    }

Starting from.Net Core 3.0 there is BitOperations.TrailingZeroCount i dont know past versions but if i look into its current .net 7 source code it is inlined into Bmi1.TrailingZeroCount which is compiler intrinsic and converted to tzcnt x86 asm instruction on supported x86 environments. it has hardware accelerated implementation for ARM and falls back to software implementation as last resort.

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