小编典典

创建具有设定位数的多个数字

algorithm

问题

我需要创建32位数字(有符号或无符号都无所谓,无论如何都不会设置最高位),并且每个数字都必须设置给定的位数。

天真的解决方案

最简单的解决方案当然是从零开始。现在,在循环中将数字加一,对位数进行计数,如果计数具有所需的值,则将数字存储到列表中,否则循环将重复一次。如果找到足够的数字,则循环将停止。当然,这工作得很好,但是一旦所需位数变得很高,它就会非常慢。

更好的解决方案

(假设)设置5位最简单的数字是设置前5位的数字。这个数字可以很容易地创建。在循环内,第一位被设置,数字向左移动一个。该循环运行了5次,我发现第一个设置了5位的数字。接下来的两个数字也很容易创建。现在,我们假装该数字为6位宽,并且最高位未设置。现在我们开始将第一个零位向右移动,因此我们得到101111、110111、111011、111101、111110。我们可以通过在前面添加另一个0并重复此过程来重复此操作。0111110、1011110、1101110等。但是,这种方式会比所需的增长速度快得多,因为使用这种简单的方法,我们忽略了1010111之类的数字。

那么,有没有一种更好的方法可以创建所有可能的排列,这是一种通用方法,无论下一个数字将有多少位,又不管我们需要设置多少个设置位,都可以使用?


阅读 269

收藏
2020-07-28

共1个答案

小编典典

您可以使用来自hackersdelight.org的可疑黑客工具

在他的书中,他具有用相同的一位数集获得下一个更高数字的代码。

如果您将其用作增加数量的原始方法,那么您要做的就是找到一个起点。通过设置N位获得第一个数字很容易。只是2 ^(N-1)-1。

您将以这种方式快速遍历所有可能的数字。

  unsigned next_set_of_n_elements(unsigned x) 
  {
     unsigned smallest, ripple, new_smallest, ones;

     if (x == 0) return 0;
     smallest     = (x & -x);
     ripple       = x + smallest;
     new_smallest = (ripple & -ripple);
     ones         = ((new_smallest/smallest) >> 1) - 1;
     return ripple | ones;
  }

  // test code (shown for two-bit digits)

  void test (void)
  {
    int bits = 2;
    int a = pow(2,bits) - 1;
    int i;

    for (i=0; i<100; i++)
    {
       printf ("next number is %d\n", a);
       a = next_set_of_n_elements(a);
    }
  }
2020-07-28