1. 程式人生 > >【筆記】Hacker's Delight - Counting Bits

【筆記】Hacker's Delight - Counting Bits

Counting 1-Bits(二進位制1的個數)

/// <summary>
/// <paramref name="n"/>二進位制1的個數
/// </summary>
public static int Population(uint n)
{
    n -= (n >> 1) & 0x5555_5555;
    n = (n & 0x3333_3333) + ((n >> 2) & 0x3333_3333);
    n = (n + (n >> 4)) & 0x0F0F_0F0F;
    n += (n >> 8);
    n += (n >> 16);

    return (int)(n & 0x0000_003F);
}


/// <summary>
/// <paramref name="n"/>二進位制1的個數
/// </summary>
public static int Population(int n)
{
    var un = (uint)n;
    un -= (un >> 1) & 0x5555_5555;
    un = (un & 0x3333_3333) + ((un >> 2) & 0x3333_3333);
    un = (un + (un >> 4)) & 0x0F0F_0F0F;
    un += (un >> 8);
    un += (un >> 16);

    return (int)(un & 0x0000_003F);
}



/// <summary>
/// <paramref name="n"/>二進位制1的個數
/// </summary>
public static int Population(ulong n)
{
    var t1 = n >> 32;
    var t2 = n & 0xFFFF_FFFF;
    t1 -= (t1 >> 1) & 0x5555_5555;
    t1 = (t1 & 0x3333_3333) + ((t1 >> 2) & 0x3333_3333);
    t2 -= (t2 >> 1) & 0x5555_5555;
    t2 = (t2 & 0x3333_3333) + ((t2 >> 2) & 0x3333_3333);
    t1 += t2;
    t1 = (t1 + (t1 >> 4)) & 0x0F0F_0F0F;
    t1 += (t1 >> 8);
    t1 += (t1 >> 16);

    return (int)(t1 & 0x0000_003F);
}



/// <summary>
/// <paramref name="n"/>二進位制1的個數
/// </summary>
public static int Population(long n)
{
    var t1 = (ulong)n >> 32;
    var t2 = (ulong)n & 0xFFFF_FFFF;
    t1 -= (t1 >> 1) & 0x5555_5555;
    t1 = (t1 & 0x3333_3333) + ((t1 >> 2) & 0x3333_3333);
    t2 -= (t2 >> 1) & 0x5555_5555;
    t2 = (t2 & 0x3333_3333) + ((t2 >> 2) & 0x3333_3333);
    t1 += t2;
    t1 = (t1 + (t1 >> 4)) & 0x0F0F_0F0F;
    t1 += (t1 >> 8);
    t1 += (t1 >> 16);

    return (int)(t1 & 0x0000_003F);
}

 Counting Leading 0’s (二進位制前導0的個數)

/// <summary>
/// <paramref name="n"/>二進位制前導0的個數
/// </summary>
public static int NumberOfLeadingZeros(this uint n)
{
    if (n == 0u) return 32;

    var c = 1;
    if ((n >> 16) == 0u) { c += 16; n <<= 16; }
    if ((n >> 24) == 0u) { c +=  8; n <<=  8; }
    if ((n >> 28) == 0u) { c +=  4; n <<=  4; }
    if ((n >> 30) == 0u) { c +=  2; n <<=  2; }

    return c - (int)(n >> 31);
}


/// <summary>
/// <paramref name="n"/>二進位制前導0的個數
/// </summary>
public static int NumberOfLeadingZeros(this int n)
{
    if (n == 0u) return 32;

    var c = 1;
    if (((uint)n >> 16) == 0) { c += 16; n <<= 16; }
    if (((uint)n >> 24) == 0) { c += 8; n <<= 8; }
    if (((uint)n >> 28) == 0) { c += 4; n <<= 4; }
    if (((uint)n >> 30) == 0) { c += 2; n <<= 2; }

    return c - (int)((uint)n >> 31);
}


/// <summary>
/// <paramref name="n"/>二進位制前導0的個數
/// </summary>
public static int NumberOfLeadingZeros(this ulong n)
{
    if (n == 0ul) return 64;

    var c = 1;
    if ((n >> 32) == 0ul) { c += 32; n <<= 32; }
    if ((n >> 48) == 0ul) { c += 16; n <<= 16; }
    if ((n >> 56) == 0ul) { c += 8; n <<= 8; }
    if ((n >> 60) == 0ul) { c += 4; n <<= 4; }
    if ((n >> 62) == 0ul) { c += 2; n <<= 2; }

    return c - (int)(n >> 63);
}


/// <summary>
/// <paramref name="n"/>二進位制前導0的個數
/// </summary>
public static int NumberOfLeadingZeros(this long n)
{
    if (n == 0L) return 64;

    var c = 1;
    if (((ulong)n >> 32) == 0L) { c += 32; n <<= 32; }
    if (((ulong)n >> 48) == 0L) { c += 16; n <<= 16; }
    if (((ulong)n >> 56) == 0L) { c += 8; n <<= 8; }
    if (((ulong)n >> 60) == 0L) { c += 4; n <<= 4; }
    if (((ulong)n >> 62) == 0L) { c += 2; n <<= 2; }

    return c - (int)((ulong)n >> 63);
}

Counting Trailing 0’s(二進位制尾數0的個數)

/// <summary>
/// <paramref name="n"/>二進位制尾數0的個數
/// </summary>
public static int NumberOfTrailingZeros(this uint n)
{
    if (n == 0) return 32;

    var c = 31;
    var t = n << 16; if (t != 0u) { c -= 16; n = t; }
    t = n << 8; if (t != 0u) { c -= 8; n = t; }
    t = n << 4; if (t != 0u) { c -= 4; n = t; }
    t = n << 2; if (t != 0u) { c -= 2; n = t; }
    t = n << 1; if (t != 0u) { c -= 1; }

    return c;
}


/// <summary>
/// <paramref name="n"/>二進位制尾數0的個數
/// </summary>
public static int NumberOfTrailingZeros(this int n)
{
    if (n == 0) return 32;

    var c = 31;
    var t = n << 16; if (t != 0) { c -= 16; n = t; }
    t = n << 8; if (t != 0) { c -= 8; n = t; }
    t = n << 4; if (t != 0) { c -= 4; n = t; }
    t = n << 2; if (t != 0) { c -= 2; n = t; }
    t = n << 1; if (t != 0) { c -= 1; }

    return c;
}


/// <summary>
/// <paramref name="n"/>二進位制尾數0的個數
/// </summary>
public static int NumberOfTrailingZeros(this ulong n)
{
    if (n == 0) return 64;

    var c = 63;
    var t = n << 32; if (t != 0ul) { c -= 32; n = t; }
    t = n << 16; if (t != 0ul) { c -= 16; n = t; }
    t = n << 8; if (t != 0ul) { c -= 8; n = t; }
    t = n << 4; if (t != 0ul) { c -= 4; n = t; }
    t = n << 2; if (t != 0ul) { c -= 2; n = t; }
    t = n << 1; if (t != 0ul) { c -= 1; }

    return c;
}



/// <summary>
/// <paramref name="n"/>二進位制尾數0的個數
/// </summary>
public static int NumberOfTrailingZeros(this long n)
{
    if (n == 0) return 64;

    var c = 63;
    var t = n << 32; if (t != 0L) { c -= 32; n = t; }
    t = n << 16; if (t != 0L) { c -= 16; n = t; }
    t = n << 8; if (t != 0L) { c -= 8; n = t; }
    t = n << 4; if (t != 0L) { c -= 4; n = t; }
    t = n << 2; if (t != 0L) { c -= 2; n = t; }
    t = n << 1; if (t != 0L) { c -= 1; }

    return c;
}