【问题标题】:Counting in different bases在不同的基础上计数
【发布时间】:2012-05-11 14:54:39
【问题描述】:

如果要计算8位以上,以2为底,结果如下:

0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 1;
0 0 0 0 0 0 1 0;
.....
1 1 1 1 1 1 1 1;

但是,如何根据不同的基数创建一个计数的算法(对于每个位),例如: 如果最低有效位以 5 为基数,而最高有效位以 2 为基数,则结果应如下所示:

0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 1;
0 0 0 0 0 0 0 2;
0 0 0 0 0 0 0 3;
0 0 0 0 0 0 0 4;
1 0 0 0 0 0 0 0;
1 0 0 0 0 0 0 1;
1 0 0 0 0 0 0 2;
...
1 0 0 0 0 0 0 4;

你能告诉我生成这些向量的算法吗?

【问题讨论】:

  • 嵌套for 循环可能是最简单的,但与所涉及的位数和碱基密切相关。仅使用单个 for 样式循环的另一种方法将依赖于为您的特定数字设计的输出例程......您具体要解决哪些问题?
  • 我正在尝试获取 8 位的所有可能组合,但每个位都对应一个特定的基数(例如:第 1 位属于基数 2;第 2 位属于基数 5.. .)
  • 我想你的意思是把所有的 0 放在左边的尺寸上,所以它是 00 01 02 03 04 10 11 12 13 14 ...
  • 这里只是挑剔:“位”被定义为具有 2 个可能状态的实体。你不能数到 2。

标签: algorithm binary decimal


【解决方案1】:

解决这个问题的一种算法是大多数学生通常在幼儿园学习的那种“ripple-carry”加法,除了稍加修改。当您将两个数字相加时,您将逐个数字地进行:首先是个位,然后是十位,然后是百位,等等。如果您必须写下一个大于 10 的数字(例如 7+8 =15),然后你把它写下来-10,然后把10“带到”下一个地方,在那里你加它(它变成1);这可能会在许多地方“涟漪”(例如 999+1=1000)。用这个算法重复加一个,我们就可以一个一个地计数了。

明确我们的目标很重要:不同的地方有不同的基地意味着什么。如果您允许位置具有任意数字范围,并代表任意数字,那么可能会发生一些不好的事情:一个数字可以用多种方式写入,和/或一些十进制数字不能写入。因此,我们将自己限制在一个“理智”的方案中,如果一个地方 i 有一个基础 bi,这意味着有效数字是 0 ,1,2,...,bi-1 (像往常一样,就像十进制一样),那个地方的数字代表 bi 乘以右边所有碱基的乘积 (bi-1 x bi-2 x ...)。例如,如果我们的基数是 [10,10,10],则数字的值将是 [1000,100,10,1];如果我们的基数是 [5,10,5],则数字的值将是 [250,50,5,1]

如何给数字加 1:

Increment the least-significant digit (LSD)
Perform ripple-carry as follows:
    Set the current place to the LSD
    Repeat as long as the current place exceeds its allowed max digit:
        Set the digit at the current place to 0
        Advance the current place one to the left
        Increment the number at the new place (now on the left)

重复上述算法,直到获得所需的所有数字。

Python:

from itertools import *

def multibaseCount(baseFunction):
    currentDigits = [0]
    while True:
        yield currentDigits[::-1]

        # add 1
        currentDigits[0] += 1

        # ripple-carry:
        for place,digit in enumerate(currentDigits):
            if currentDigits[place]>=baseFunction(place):    # if exceeds max digit
                currentDigits[place] = 0         # mod current digit by 10
                if place==len(currentDigits)-1:  # add new digit if doesn't exist
                    currentDigits += [0]
                currentDigits[place+1] += 1      # add 1 to next digit
            else:    # doesn't exceed max digit; don't need to carry any more
                break

演示,其中 n 位置的底数为 n+1:

>>> for digits in islice(multibaseCount(lambda n:n+1),30):
...     print( ''.join(map(str,digits)).zfill(5) )
... 
00000
00010
00100
00110
00200
00210
01000
01010
01100
01110
01200
01210
02000
02010
02100
02110
02200
02210
03000
03010
03100
03110
03200
03210
10000
10010
10100
10110
10200
10210

【讨论】:

    【解决方案2】:

    如果您真的只对这种格式的八位“数字”感兴趣,这里有一些伪代码可以帮助您入门:

    for (a=0; a<2: a++)
      for (b=0; b<5; b++)
        for (c=0; c<2; c++)
          for (d=0; d<2; d++)
            for (e=0; e<2; e++)
              for (f=0; f<2; f++)
                for (g=0; g<2; g++)
                  for (h=0; h<2; h++)
                    printf("%d%d%d%d%d%d%d%d\n", a, b, c, d, e, f, g, h);
    

    在这种情况下,它将是基数 2、5、2、2、2、2、2、2。根据需要更改索引。

    【讨论】:

      【解决方案3】:

      为时已晚,但这是 C 中的解决方案。

      #include <stdio.h>
      #include <assert.h>
      
      void
      odo(int base, int len)
      {
          int stack[len+1];
          int pos=0;
          #define DIGIT (stack[pos])
          #define LOOP(code) for(int i=0; i<len; i++) code
          #define PRINT LOOP(printf("%d", stack[i]));printf("\n");
          LOOP(stack[i]=-1);
          while(pos>=0)
          {
              if (pos<len-1)
              {
                  if (DIGIT<base)
                  {
                      DIGIT++;
                      pos++;
                      assert(DIGIT==-1);
                  }
                  else
                  {
                      DIGIT=-1;
                      pos--;
                      continue;
                  }
              }
              else
              {
                  assert(pos==len-1);
                  if (DIGIT<base)
                  {
                      DIGIT++;
                      PRINT;
                  }
                  else
                  {
                      DIGIT=-1;
                      pos--;
                  }
              }
          }
      }
      
      int
      main(void)
      {
          odo(4,6);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-07
        • 2016-10-05
        • 1970-01-01
        • 2018-02-25
        • 1970-01-01
        • 2014-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多