计算每个位在整数范围内设置的次数

时间:2012-06-25 02:03:05

标签: algorithm bit-manipulation

给出从M到N的整数范围,其中 M和N可能不是2的幂。是否有 有效的方法来计算每个的次数 位设置了吗?

例如0到10的范围

0   0000
1   0001
2   0010
3   0011
4   0100
5   0101
6   0110
7   0111
8   1000
9   1001
10  1010

我想在每一列中设置每个位的时间计数,在这种情况下为3,4,5,5。

2 个答案:

答案 0 :(得分:6)

每个位级别都有2^power 0s后跟2^power 1s的模式。

所以有三种情况:

  1. MNM = 0 mod 2^(power+1)N = 2^(power+1)-1 mod 2^(power+1)时。在这种情况下,答案只是(N-M+1) / 2

  2. MN当整数除以2^(power+1)时,M和N都是相同的数字。在这种情况下,有几个子类:

    1. MN都是MN =整数除以2^(power)时的相同数字。在这种情况下,如果是N < 2^(power) mod 2^(power+1),则答案为0,否则答案为N-M+1
    2. 否则他们是不同的,在这种情况下答案是N - (N/2^(power+1))*2^(power+1) + 2**(power)(整数除法)N > 2^(power) mod 2^(power+1),否则答案是(M/2^(power+1))*2^(power+1) - 1 - M
  3. 最后一种情况是当整数除以2^(power+1)时,M和N =不同的数字。在这种情况下,您可以结合使用1和2的技巧。查找M(M/(2^(power+1)) + 1)*(2^(power+1)) - 1之间的数字数。然后在(M/(2^(power+1)) + 1)*(2^(power+1))(N/(2^(power+1)))*2^(power+1)-1之间。最后是(N/(2^(power+1)))*2^(power+1)N

  4. 如果这个答案中存在逻辑错误,请告诉我,这很复杂,我可能会略微搞砸了。

    更新:

    python实现

    def case1(M, N):
      return (N - M + 1) // 2
    
    def case2(M, N, power):
      if (M > N):
        return 0
      if (M // 2**(power) == N // 2**(power)):
        if (N % 2**(power+1) < 2**(power)):
          return 0
        else:
          return N - M + 1
      else:
        if (N % 2**(power+1) >= 2**(power)):
          return N - (getNextLower(N,power+1) + 2**(power)) + 1
        else:
          return getNextHigher(M, power+1) - M
    
    
    def case3(M, N, power):
      return case2(M, getNextHigher(M, power+1) - 1, power) + case1(getNextHigher(M, power+1), getNextLower(N, power+1)-1) + case2(getNextLower(N, power+1), N, power)
    
    def getNextLower(M, power):
      return (M // 2**(power))*2**(power)
    
    def getNextHigher(M, power):
      return (M // 2**(power) + 1)*2**(power)
    
    def numSetBits(M, N, power):
      if (M % 2**(power+1) == 0 and N % 2**(power+1) == 2**(power+1)-1):
        return case1(M,N)
      if (M // 2**(power+1) == N // 2**(power+1)):
        return case2(M,N,power)
      else:
        return case3(M,N,power)
    
    if (__name__ == "__main__"):
      print numSetBits(0,10,0)
      print numSetBits(0,10,1)
      print numSetBits(0,10,2)
      print numSetBits(0,10,3)
      print numSetBits(0,10,4)
      print numSetBits(5,18,0)
      print numSetBits(5,18,1)
      print numSetBits(5,18,2)
      print numSetBits(5,18,3)
      print numSetBits(5,18,4)
    

答案 1 :(得分:0)

它可以像 -

一样简单

取x1 = 0001(在最右边的列找到1),x2 = 0010,x3 = 0100等等..

现在,在一个循环中 -

n1 = n2 = n3 = 0
for i=m to n:
    n1 = n1 + (i & x1)
    n2 = n2 + (i & x2)
    n3 = n3 + (i & x3)

其中 - ni =第i列中的1的数字(从右起)