Java在数字范围内计算一位

Java在数字范围内计算一位,java,binary,bit,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; }

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

所以我必须在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;
}

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

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

for (int i = 0; i < TABLE_SIZE; ++i)
  table = hammingWeight(i);
当然,您必须找到一种方法来指定比
long
数据类型长的数字,但这应该不会太难,只需要考虑符号和移位。

您可以使用

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

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

我想您需要使用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
2的幂

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

说明:如果您有一个以位表示的数字表,则后半部分右边只有一位(n/2额外位)

因此,10^16应该是一个长期的可行方案

更详细的情况我不能凭良心说出来。

对于0..2n-1范围,对于一些n,每个数字都可以用n位表示,在整个范围内,给定位的数字正好有一半是0,另一半是1。例如,
0..7
给出000001010011100101110111,其中四个数字的每一位都是0,四个数字的每一位都是1。因此,所有八个数字的汉明权重之和是2n*n/2,这里是8*3/2或12

因此,计算从0到9007199254740992(小于1016的两个最大幂)的总和是非常简单的


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

这个项目是Euler吗?我相当确信,有一种模式可以让您“计数”没有列举所有的可能性。没有,但学校额外的编程作业。我只是需要一些帮助来解决这个问题。也许你应该把这个贴到数学板上。。。但是,如果您确实想用bruteforce方法来实现这一点:使用
biginger
,您可以用它来表示任何整数(只要您有足够的内存…)。提示:+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