为什么这种离散编码计算不正确?我错过了什么吗?

Why is this discrete encoding not calculating properly? Am i missing something?

我正在尝试将一些因子编码为离散数,然后将离散数逆向工程返回其因子 - 但是一旦我添加了足够多的因子,反向过程就不会显示正确的数字。

a = 3
b = 13
c = 7
d = 8
e = 3
f = 2

state = (((((b)*20+c)*10+d)*10+e)*5+f)*5
# If i add "a*4" to the front of the line (as shown in this line below), A and B is no longer showing correct

state = ((((((a)*4+b)*20+c)*10+d)*10+e)*5+f)*5

print(state)

print("f:", state // 5 % 5)
state = state // 5
print(state)

print("e:", state // 5 % 5)
state = state // 5
print(state)

print("d:", state // 10 % 10)
state = state // 10
print(state)

print("c:", state // 10 % 10)
state = state // 10
print(state)

print("b:", state // 20 % 20)
state = state // 20
print(state)

print("a:", state // 4 % 4)
state = state // 4
print(state)

您正在尝试做一些不可能的事情。如果你定义

def make_state(a,b,c,d,e,f):
    return ((((((a)*4+b)*20+c)*10+d)*10+e)*5+f)*5

然后 make_state(3,13,7,8,3,2)make_state(4,9,7,8,3,2) 评估为相同的状态 (1269585)。因此不可能从 1269585 开始并将该数字解码回原始向量。 make_state() 不是 one-to-one。它丢失了信息。较小的计算 state = (((((b)*20+c)*10+d)*10+e)*5+f)*5 也会丢失信息(至少在对记录的向量没有严格限制的情况下)。通常,对于任何整数 x,函数 f(a,b): return ax+b 将无法成为 one-to-one,因此除非我遗漏了一些东西,否则整个编码数字序列的方法都是行不通的。

另一方面,如果已知数字的上限,则可以执行类似的操作。例如,如果 a,b,c,d,e,f 分别是 non-negative 个小于 4,20,10,10,5,5 的整数,则函数

def encode(a,b,c,d,e,f):
    return 5*(5*(10*(10*(20*a+b)+c)+d)+e)+f

可以反转。这是从 division algorithm 得出的,它指出对于 a,bb > 0 的任何整数,a 可以 唯一地 写成 a = b*q + r0 <= r < b。在上面的函数中,f 在那个范围 中除以 5 后可以唯一恢复,() 中的部分也可以 5*( ... ) + f。从那里你可以恢复 e,等等。一系列 5 divmods 就足够了。请注意,a 上的界限不会进入计算。

解码:

def decode(n):
    q,f = divmod(n,5)
    q,e = divmod(q,5)
    q,d = divmod(q,10)
    q,c = divmod(q,10)
    a,b = divmod(q,20)
    return a,b,c,d,e,f

例如:

>>> encode(3,13,7,8,3,2)
184467
>>> decode(184467)
(3, 13, 7, 8, 3, 2)

更一般地说:

def encode(numbers, choices):
    #0 <= numbers[i] < choices[i] for all i
    n = numbers[0]
    for x,y in zip(numbers[1:],choices[1:]):
        n = n*y + x
    return n

def decode(n,choices):
    numbers = []
    for d in choices[:0:-1]:
        n,r = divmod(n,d)
        numbers.append(r)
    numbers.append(n)
    return numbers[::-1]

工作方式如下:

>>> encode([3,13,7,8,3,2],[4,20,10,10,5,5])
184467
>>> decode(184467,[4,20,10,10,5,5])
[3, 13, 7, 8, 3, 2]