8

我正在尝试通过 PHP 解决以下问题。目的是根据整数种子生成一个唯一的 6 字符字符串,并包含预定义的字符范围。第二个要求是字符串必须随机出现(因此如果代码 1 为 100000,则代码 2 为 100001 和 3 100002 是不可接受的)

字符范围为:

  • 大写 AZ 不包括:B、I、O、S 和 Z
  • 0-9 不包括:0、1、2、5、8

所以如果我没记错的话,总共有 26 个字符。我的第一个想法是从编号 7962624 开始从 base 10 编码到 base 24。7962624 + 种子也是如此,然后 base24 编码该数字。

这给了我字符 0-N。如果我以以下方式替换结果字符串,则我满足第一个条件:

B=P, I=Q, 0=R, 1=T, 2=U, 5=V, 8=W

所以在这一点上,我的代码看起来像这样:

1=TRRRR, 2=TRRRT, 3=TRRRU

所以我对各位大师的问题是:我怎样才能创建一个行为一致的方法(因此给定整数的返回字符串总是相同的)并满足上述 2 个要求?我已经花了整整 2 天的时间在这上面,没有将 700,000,000 个代码转储到数据库中并随机检索它们,我完全没有想法。

斯蒂芬

4

1 回答 1

7

如果您将输入序列 1,2,3... 应用到以素数为模的线性映射,您将得到一个看起来相当随机的序列。唯一代码的数量仅限于质数,因此您应该选择一个较大的。只要您选择的乘数不能被素数整除,生成的代码就会是唯一的。

这是一个例子:使用 6 个字符,您可以创建 26 6 =308915776 个唯一字符串,因此合适的素数可以是 308915753。因此,此函数将生成超过 300.000.000 个唯一代码:

function encode($num) {
    $scrambled = (240049382*$num + 37043083) % 308915753;
    return base_convert($scrambled, 10, 26);
}

确保在 64 位 PHP 上运行它,否则乘法将溢出。在 32 位上,您必须使用bcmath. 为数字 1 到 9 生成的代码是:

n89a2d
hdh4jo
biopb9
5o6k2k
3eek5
k8m9aj
ee4424
8jbojf
2ojjb0

剩下的就是填充有时会丢失的初始 0 并替换字母和数字,这样就不会产生任何禁止的字符。

正如您所看到的,没有明显的模式,但是有一些时间,有足够的动力并且可以访问其中一些代码的人将能够找出发生了什么。更安全的替代方法是使用具有小块大小的加密算法,例如Skip32

于 2013-10-03T14:49:24.127 回答