Java在数字范围内计算一位

时间:2013-12-31 16:42:33

标签: java binary bit

我在计算大量范围内的一位时遇到问题。

所以我必须在1到1000的eq数范围内计算一位 这是4938。

public static long countRangeOneBits(long n){
    long t = 0;
    for (long i = 1; i <= n; i++) {
        long x = i;
        while (x > 0) {
            t += x%2;
            x /= 2;
        }
    }
    return t;
}

好的,这很好用,但我需要计算范围1..10 ^ 16。首先,java不会计算那么大的数字,至少对于长数据类型。我有其他选择,或者你们有任何关于如何处理这个问题的提示。

| From 1 To        | Total             |
|                1 |                1  |
|               10 |               14  |
|              100 |              319  |
|             1000 |             4938  |
|            10000 |            64613  |
|           100000 |           815030  |
|          1000000 |          9884999  |
|         10000000 |        114434632  |
|        100000000 |       1314447116  |
|       1000000000 |      14846928141  |
|  100000000000000 | 2306412649693200  |
| 1000000000000000 |24784747400675300  |

5 个答案:

答案 0 :(得分:1)

由于您需要使用这么多数字,因此查找表可能是最简单的方法:

final int TABLE_SIZE = 65536;
int[] table = new int[TABLE_SIZE];

for (int i = 0; i < TABLE_SIZE; ++i)
  table = hammingWeight(i);

然后您可以将您的数字分成16位块并将它们的所有权重相加以计算结果,因为汉明重量可以计算为起始数的两个部分的权重之和,例如:

long number = 12445235;
int weight = table[number & 0xFFFF] + table[(number >>> 16) & 0xFFFF];

当然,您必须找到一种方法来指定长度超过long数据类型的数字,但这不应该太难,只关心标志和转移。

答案 1 :(得分:1)

您可以使用

// this turns into a single machine instruction
int numOfBitSet = Long.bitCount(n);

这将计算为最多9 * 10 ^ 18的值设置的位数。

答案 2 :(得分:1)

我猜你需要玩2 ^ n。作为从0到(2 ^ n - 1)= n * 2 ^(n-1)的1位的总数。

在程序中,这就是你想要的

private static long getBits(long l){
        if(l == 0){
            return 0;
        }else if(l == 1){
            return 1;
        }
        boolean isPowerOf2Minus1 = (l & (l+1)) == 0;
        long maxBitNum = Long.highestOneBit(isPowerOf2Minus1 ? l+1 : l);
        int maxBit = Long.numberOfTrailingZeros(maxBitNum);
        if((l & (l+1)) == 0){
            return maxBit * (maxBitNum >> 1);
        }
        long diff = l - maxBitNum;
        return diff + 1 + getBits(maxBitNum - 1) + getBits(diff);
    }

以下结果

                   1 :                    1
                  10 :                   17
                 100 :                  319
                1000 :                 4938
               10000 :                64613
              100000 :               815030
             1000000 :              9884999
            10000000 :            114434632
           100000000 :           1314447116
          1000000000 :          14846928141
         10000000000 :         164293127179
        100000000000 :        1809725656079
       1000000000000 :       19809942118413
      10000000000000 :      214309466746894
     100000000000000 :     2306412649693201
    1000000000000000 :    24784747400675348
   10000000000000000 :   264286863212871700
  100000000000000000 :  2804216299269586964

答案 3 :(得分:0)

对于2的权力

countRangeOneBits(n)= 2 * countRangeOneBits(n / 2)+(n / 2)

说明:如果你有一个数字表作为位,则后半部分只有一位(n / 2个额外位)。

所以10 ^ 16应该是长的。

更多细节我不能凭良心传递。

答案 4 :(得分:0)

对于范围0..2 n -1,对于某些n,每个数字可以用n位表示,并且在整个范围内,对于给定位的正好一半数字为0,另一半为1。例如,0..7给出000,001,010,011,100,101,110,111,其中每个位为0,其中4个为1,其中4个为1。因此,所有八个数字的汉明权重的是2 n * n / 2,这里是8 * 3/2或12。

因此计算从0到9007199254740992(两个小于10 16 的最大幂)的总和是非常微不足道的。

获取最后的992800745259008值更难...你可以通过从每个值中减去9007199254740992并重复上述过程来递归计算它们,但是为每个值加1表示你减去的9007199254740992。