简体   繁体   English

查找具有最大/最小位数集的数字

[英]Finding a numbers with the largest/smallest number of bits set

Given a range of integers, how do I find the numbers within the range with the largest and the lowest number of bits set?给定一个整数范围,如何找到设置了最大和最小位数的范围内的数字?

For example, given the range [32, 65] , 63 has the largest number of bits set (ie six, because the binary representation is 111111 ) and 32 and 64 have the lowest (ie one, because the binary representation are 100000 and 1000000 ).例如,给定范围[32, 65] , 63 设置的位数最多(即 6,因为二进制表示是111111 ),而 32 和 64 设置的位数最少(即 1,因为二进制表示是1000001000000 )。

Has to work fast for very large numbers/ranges (2^50).对于非常大的数字/范围(2^50),必须快速工作。

Try to find the highest power of 2 that is within the range.尝试找出范围内 2 的最高幂。 This can be done by taking the upper bound and ANDing it with itself minus one in a loop, like:这可以通过取上限并将其与自身减一在循环中进行 AND 运算来完成,例如:

temp = upper_bound;
while( (temp & (temp-1)) != 0) {
    temp = temp & (temp-1);
}

if(temp < lower_bound) {
    // No power of 2 found within range
}

If no power of 2 within the range is found by the previous step;如果上一步在范围内没有找到 2 的幂; you would've found a power of 2 that is not in range.你会发现 2 的幂不在范围内。 Clear the corresponding bit in the upper and lower bounds and recurse;清除上下界对应位并递归; like:喜欢:

void find_bits(unsigned int lower_bound, unsigned int upper_bound, unsigned int extra_bits) {
    unsigned int temp = upper_bound;
    while( (temp & (temp-1)) != 0) {
        temp = temp & (temp-1);
    }

    if(temp < lower_bound) {
        find_bits(lower_bound ^ temp, upper_bound ^ temp, extra_bits + 1);
        return;
    }

If zero is within the range, then the smallest number of set bits is zero (from the number zero).如果零在范围内,则设置位的最小数量为零(从数字零开始)。 Otherwise, the smallest number of set bits is one (from any power of 2 within range, including the highest power of 2 you found).否则,设置位的最小数量为 1(范围内的任意 2 次幂,包括您找到的最高 2 次幂)。 Don't forget to account for any extra bits that were previously cleared:不要忘记考虑之前清除的任何额外位:

    if(lower_bound == 0) {
        least_set_bits = 0 + extra_bits;
    } else {
        least_set_bits = 1 + extra_bits;
    }

If the highest power of 2 within range minus 1 is also within the range, then the largest number of set bits will be however many bits is in highest power of 2 within range minus 1. Otherwise, the upper bound must have been the same as the lower bound and therefore the largest number of set bits is equal to the smallest number of set bits:如果范围负 1 内的 2 的最高幂也在范围内,则设置位的最大数量将是但许多位在范围负 1 内的 2 的最高幂。否则,上限必须与下限,因此最大的设置位数等于最小的设置位数:

    if(temp - 1 < lower_bound) {
        most_set_bits = least_set_bits;
    } else {
        temp--;
        most_set_bits = 0;
        while(temp > 0) {
            temp >>= 1;
            most_set_bits++;
        }
        most_set_bits += extra_bits;
    }

All of the above combined (and untested and probably buggy; and definitely not able to handle some corner cases - eg if the range is [0, 0]):以上所有组合(并且未经测试并且可能有问题;并且绝对无法处理某些极端情况 - 例如,如果范围是 [0, 0]):

void find_bits(unsigned int lower_bound, unsigned int upper_bound, unsigned int extra_bits) {
    unsigned int temp = upper_bound;
    unsigned int least_set_bits;
    unsigned int most_set_bits;

    while( (temp & (temp-1)) != 0) {
        temp = temp & (temp-1);
    }

    if(temp < lower_bound) {
        find_bits(lower_bound ^ temp, upper_bound ^ temp, extra_bits + 1);
        return;
    }

    if(lower_bound == 0) {
        least_set_bits = 0 + extra_bits;
    } else {
        least_set_bits = 1 + extra_bits;
    }

    if(temp - 1 < lower_bound) {
        most_set_bits = least_set_bits;
    } else {
        temp--;
        most_set_bits = 0;
        while(temp > 0) {
            temp >>= 1;
            most_set_bits++;
        }
        most_set_bits += extra_bits;
    }

    printf("Least set bits is %u, most set bits is %u.\n", least_set_bits, most_set_bits);
}

Given the range [ lower , upper ] with unsigned lower and upper , let diff = lower ^ upper be the bits that are different in lower and upper .给定范围 [ lower , upper ] 与unsigned lowerupper ,让diff = lower ^ upperlowerupper不同的位。

If diff is zero, the lower and upper are identical, so the least number of bits and the greatest number of bits set in the range is the number of bits set in lower .如果diff为零,则lowerupper相同,因此范围中设置的最少位数和最大位数就是lower设置的位数。

Otherwise, let n be the number of the greatest bit set in diff , starting counting from 0 for the least significant bit.否则,让ndiff设置的最大位的编号,从 0 开始计数最低有效位。 Let mask = (2u << n) - 1 be a mask for the bits up to and including bit n .mask = (2u << n) - 1是直到并包括位n的位的掩码。 (Note 2u is correct.) Partition lower and upper into shared high bits and separate low bits: (注2u是正确的。)将lowerupper划分为共享的高位和单独的低位:

shared = lower & ~mask;
lower &= mask;
upper &= mask;

Count the bits set in shared .计算shared设置的位。 They are necessarily set in any value in the original [ lower , upper ].它们必须设置为原始 [ lower , upper ] 中的任何值。 Below, we solve for the new lower and upper .下面,我们求解新的lowerupper Then the solution for the original values is obtained by adding the number of bits set in shared .然后通过添加shared设置的位数来获得原始值的解决方案。

If lower is zero, the least number of bits set is zero, since 0 is in [ lower , upper ], Otherwise, it is one, since 1u << n is in [ lower , upper ].如果lower为零,则设置的最少位数为零,因为 0 在 [ lower , upper ] 中,否则为 1,因为1u << n在 [ lower , upper ] 中。

If upper equals mask , the greatest number of bits set is n+1 , the number of bits set in mask .如果upper等于mask ,则设置的最大位数为n+1 ,即mask设置的位数。 Otherwise, it is n , since (1u << n) - 1 is in [ lower , upper ].否则,它是n ,因为(1u << n) - 1在 [ lower , upper ] 中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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