【问题标题】:Standard Positional to Bijective Base Conversion标准位置到双射基转换
【发布时间】:2017-11-29 07:23:20
【问题描述】:

我们知道b-based standard positional 数字系统使用数字, 0, 1, 2, ..., b-1。但是bijective number system 使用数字1, 2, ..., b。所以4-based 标准数字系统序列看起来像,

0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33 (base-4, 16th number standard)
100 (base-4, 17th number standard)
101
.
.
.

另一方面,4-based 的双射数字系统看起来像,

λ (base-4, 1st number, empty-string)
1
2
3
4
11
12
13
14
21
22
23
24
31
32
33 (base-4, 16th number bijective)
34 (base-4, 17th number bijective)
41 
.
.
.

例子:

34152(双射基数 5)=3×54 + 4×53 + 1×52 + 5×51 + 2×1 = 2427(十进制)。 119A(双射以 10 为底,“A”代表数字值 10)=1×103 + 1×102 + 9×101 + 10×1 = 1200(十进制)。

我想知道是否有任何简单的方法可以在同一基数中找到n'th 位置双射值。

例如,

让我们说base-4 5th 位置值 = 10(标准)5th 位置值 = 11(双射) 。任何伪代码都可以理解这个概念。

【问题讨论】:

  • 以您的声誉和成为会员这么久,您应该比这更清楚。您应该知道how to ask good questions 以及如何创建Minimal, Complete, and Verifiable Example
  • 在您的“双射”系统中如何表示零?还有,双射系统如何表示位置系统中33100133333对应的数字?
  • 双射数制时没有零@JonathanLeffler
  • 有趣的是,这样的数字系统仍然有效地具有前导零。例如,以 5 为底,双射的 3/5 的答案是什么?结果似乎是第n个位置双射值仅比相应的标准值大1。不能简单地在标准代表中计算,然后通过加 1 进行转换吗?
  • 您想如何将数字存储在您的 C 程序中?作为字符串?

标签: math numbers base


【解决方案1】:

如果标准 base-n 系统中的数字包含 no 个零,则该数字与双射 base-n 具有相同的表示。

因此您需要在标准编号中查找零。当你找到一个零时,将它替换为双射中的最大符号,并将左边的元素递减。

简单示例:

10 decimal ->  A bijective because 0 becomes A and 1 decrements to zero
20 decimal -> 1A bijective because 0 becomes A and 2 decrements to 1

作为一种特殊情况,您必须处理零序列。

简单示例:

200 decimal ->  19A bijective (i.e. step 1: 1A0 step 2: 19A)

你也可以这样看

200 decimal is constructed as 2*100 + 0*10 + 0*1 = 200 decimal

对于双射,你不能有零,所以你会这样做:

19A bijective is constructed as 1*100 + 9*10 + 10*1 = 200 decimal

完成一个更复杂的例子:

110 decimal ->  AA bijective (i.e. step 1: 10A step 2: AA)

【讨论】:

  • 他忘记了+1。否则 100 -> 101 -> 41。
  • 在 base-4 中 100 将转到 34 双射(即 100 base4 是 16 十进制 (1*16+0*4+0*1) 和双射 34 (3*4 + 4 = 16 十进制))
  • @DavidBowling - 我们可以同意34 在base-4 双射中是十进制的16 位吗?因为它是 3*4 + 4*1 = 16 十进制?标准 base-4 中的 100 也是十进制的 16 位?
  • @DavidBowling - 这是因为 OP 没有将 empty string 算作双射中的一个位置。所以 OP 将双射视为 {1, 2, 3, 4, 11, ...} 而 OP 将标准 base-4 视为 {0, 1, 2, 3, 10, ...} 所以也许我误解了操作问题。我的建议映射在相同的值之间 - 而不是在位置之间......嗯......
  • @SazzadHissainKhan - 在这种情况下,我的答案应该是你正在寻找的 :-)
【解决方案2】:

此例程实现转换。 (解决了@4386427的方法。)如果你想要另一个版本,其中100(base 4 std)-> 41(base 4 bij')然后用-D NO_EMPTY_STRING编译

#include <stdio.h>
#include <string.h>
void print_be_digits(const char *prefix, const unsigned char *le_num, size_t len)
{
  size_t i;
  printf("%s", prefix);
  for(i=0; i<len; i++)
  {
    printf("%d ", (int)le_num[len-i-1]);
  }
  printf("\n");
}

void nth_bij(int n, int k)
{
  ssize_t i;
  size_t std_len;
  size_t bij_len;
  size_t work;
  unsigned char le_std_digits[256];
  unsigned char le_bij_digits[256];

  //convert to standard radix-k digits
  work = n;
  for(std_len = 0; work; std_len++)
  {
    le_std_digits[std_len] = work % k;
    work /= k;
  }

  print_be_digits("  std: ", le_std_digits, std_len);

  //convert standard to bij
  memcpy(le_bij_digits, le_std_digits, std_len);
  bij_len = std_len;

  #ifdef NO_EMPTY_STRING
  // Step 1: increment LSd
  le_bij_digits[0]++;
  #endif

  // Step 2: borrow on zeros
  // scan back from the end
  for(i=bij_len-1; i>= 0; i--)
  {
    //if we find a zero, borrow, and ripple toward MSd as necessary
    if(le_bij_digits[i] == 0)
    {
      size_t j;

      //Ripple borrow toward MSd, as necessary
      for(j=i+1; j<bij_len; j++)
      {
        le_bij_digits[j-1] = k; //k is the radix

        if(--le_bij_digits[j])
        {
          break;
        }
      }//end ripple

      //adjust bij_len if we rippled to the end
      if(j == bij_len)
      {
        bij_len--;
      }
    }
  }//end scan
  print_be_digits("  bij: ", le_bij_digits, bij_len);
}

简单驱动:

int main(int argc, char *argv[])
{
  printf("Test: 16 decimal (->base 4): \n");
  nth_bij(16,4);
  printf("\n");

  printf("Test: 8 decimal (->base 2): \n");
  nth_bij(8,2);
  printf("\n");

  printf("Test: 13 decimal (->base 2): \n");
  nth_bij(13,2);
  printf("\n");

  printf("Test: 2427 decimal (->base 5): \n");
  nth_bij(2427, 5);
  printf("\n");

  printf("Test: 1200 decimal (->base 10): \n");
  nth_bij(1200, 10);
  printf("\n");
}

为我的版本编译:

$ gcc -D NO_EMPTY_STRING bij.c
$ ./a.exe
Test: 16 decimal (->base 4):
  std: 1 0 0
  bij: 4 1

Test: 8 decimal (->base 2):
  std: 1 0 0 0
  bij: 1 2 1

Test: 13 decimal (->base 2):
  std: 1 1 0 1
  bij: 2 2 2

Test: 2427 decimal (->base 5):
  std: 3 4 2 0 2
  bij: 3 4 1 5 3

Test: 1200 decimal (->base 10):
  std: 1 2 0 0
  bij: 1 1 10 1

为@4386427 的版本编译:

$ gcc bij.c
$ ./a.exe
Test: 16 decimal (->base 4):
  std: 1 0 0
  bij: 3 4

Test: 8 decimal (->base 2):
  std: 1 0 0 0
  bij: 1 1 2

Test: 13 decimal (->base 2):
  std: 1 1 0 1
  bij: 2 2 1

Test: 2427 decimal (->base 5):
  std: 3 4 2 0 2
  bij: 3 4 1 5 2

Test: 1200 decimal (->base 10):
  std: 1 2 0 0
  bij: 1 1 9 10

【讨论】:

  • 这只是转换的中间步骤。我稍后会在这里粘贴代码。
  • 亲爱的大家,对于误导性问题,我深表歉意,请参阅我更正后的帖子。实际上我忘记了双射数列的空字符串。在 base-4 中,33 std = 33 双射,100 std = 34 双射。见这里en.wikipedia.org/wiki/…
  • 是的,我必须改变处理相邻 0 序列的方式。它与第一篇文章很接近,但略有不同。同意这是一段旅程。我已经有一段时间没有这么有趣的编程了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多