标准位置到双射基础转换
Standard Positional to Bijective Base Conversion
我们知道 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" 表示数字值十)= 1×103 + 1×102 + 9×101 + 10×1 = 1200
(十进制)。
我想知道是否有任何简单的方法可以在相同的基础上找到 n'th
位置双射值。
例如,
让我们说 base-4
5th 位置值 = 10(标准) 但 5th 位置值 = 11(双射)。任何伪代码都可以理解这个概念。
如果标准 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)
这个例程实现了转换。 (解决了 @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
我们知道 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" 表示数字值十)= 1×103 + 1×102 + 9×101 + 10×1 = 1200
(十进制)。
我想知道是否有任何简单的方法可以在相同的基础上找到 n'th
位置双射值。
例如,
让我们说 base-4
5th 位置值 = 10(标准) 但 5th 位置值 = 11(双射)。任何伪代码都可以理解这个概念。
如果标准 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)
这个例程实现了转换。 (解决了 @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