计算一个段中的个数(二进制)

Hol*_*lon 4 c algorithm math binary

我现在正在解决一个问题,如下所示:

有两个数 x1 和 x2,且 x2 > x1。

例如 x1 = 5;x2 = 10;

我必须找到二进制表示中 x1 和 x2 之间的总和。

5 = 101   => 2 ones
6 = 110   => 2 ones
7 = 111   => 3 ones
8 = 1000  => 1 one
9 = 1001  => 2 ones
10= 1010  => 2 ones
so the sum will be 
sum = 2 + 2 + 3 + 1 + 2 + 2 = 12 ones;
Run Code Online (Sandbox Code Playgroud)

所以我成功地编写了一个代码,甚至没有将数字转换为二进制并浪费执行时间。

2^n我注意到每个with中的个数n >= 11 Ex :2^1 => num of ones is 1 2^2 => 1 2^15 => 1

如果需要,您可以在这里测试: https://www.rapidtables.com/convert/number/decimal-to-binary.html ?x=191

每个之间2^n and 2^(n+1)都有连续的数字,正如您将在本例中看到的那样:

      num              number of ones
2^4 = 16                      1
      17                      2
      18                      2
      19                      3
      20                      2
      21                      3
      22                      3
      23                      4
      24                      2
      25                      3
      26                      3
      27                      4
      28                      3
      29                      4
      30                      4
      31                      5
2^5 = 32                      1
Run Code Online (Sandbox Code Playgroud)

所以我写了一个代码可以找到之间有多少个2^n and 2^(n+1)

int t;                ////turns
int bin = 1;              //// numbers of ones in the binary format ,,, and 1 for 2^5
int n1 = 32;          //// 2^5  this is just for clarification 
int n2 = 64;          //// 2^6
int *keep = malloc(sizeof(int) * (n2 - n1);             ///this is to keep numbers because 
                                      /// i'll need it later in my consecutive numbers
int i = 0;
int a = 0;
n1 = 33               //// I'll start from 33 cause "bin" of 32 is "1";

while (n1 < n2)       /// try to understand it now by yourself
{
    t = 0;
    while (t <= 3)
    {
        
        if (t == 0 || t == 2) 
            bin = bin + 1;
        
        else if (t == 1) 
            bin = bin;
        
        else if (t == 3)
        {
            bin = keep[i];
            i++;
        }
        keep[a] = bin;
        a++;
        t++;
    }
    n1++;
}
Run Code Online (Sandbox Code Playgroud)

无论如何,正如你所看到的,我即将解决问题,但它们给了我巨大的数字,我必须找到它们之间的数字,不幸的是,我已经尝试了很多方法来使用上面的代码计算“总和”,但我最终花了时间执行问题。
前任:1, 1000000000 the numbers of ones is >>> 14846928141

所以你能给我一点提示我下一步该怎么做吗,提前谢谢。

我这样做是为了 CodeWar 挑战:https://www.codewars.com/kata/596d34df24a04ee1e3000a25/train/c

chq*_*lie 5

1您可以通过计算范围内的位数n并对任何子范围使用简单的减法来解决此问题:

#include <stdio.h>
#include <stdlib.h>

/* compute the number of bits set in all numbers between 0 and n excluded */
unsigned long long bitpop(unsigned long long n) {
    unsigned long long count = 0, p = 1;
    while (p < n) {
        p += p;
        /* half the numbers in complete slices of p values have the n-th bit set */
        count += n / p * p / 2;
        if (n % p >= p / 2) {
            /* all the numbers above p / 2 in the last partial slice have it */
            count += n % p - p / 2;
        }
    }
    return count;
}    

int main(int argc, char *argv[]) {
    unsigned long long from = 1000, to = 2000;

    if (argc > 1) {
        to = from = strtoull(argv[1], NULL, 0);
        if (argc > 2) {
            to = strtoull(argv[1], NULL, 0);
        }
    }

    printf("bitpop from %llu to %llu: %llu\n", from, to, bitpop(to + 1) - bitpop(from));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)