- 它应该是一个唯一的字符串;
- 字符串长度应为8个字符;
- 它应该包含2个数字;
- 所有符号(非数字字符)应为大写。
我的意图是做这样的事情:
- 从0到9生成2个随机值-它们将用作字符串中的数字;
- 从0到25生成6个随机值并将它们加上64-它们将用作6个符号;
- 将所有内容连接成一个字符串;
- 检查该字符串是否已存在于数据库中;如果不存在-重复上述步骤。
问题:您能否请提供建议,以改进此算法以更具确定性?
谢谢。
- 字符串应该是唯一的;
- 字符串长度应为8个字符;
- 它应该包含2个数字;
- 所有符号(非数字字符) - 应大写。
假设:
然后您提出的方法有两个问题。一个是字母A-Z是ASCII 65-90,而不是64-89。另一个是它不能在可能的字符串空间内平均分配数字。可以通过执行以下操作来解决这个问题:
对于两个不同的整数,有28种可能性((8*8-8)/2),字母有266种可能性,数字有100种可能性,有效组合的总数为Ncomb=864964172800=8.64 x 1011。
或者,使用40位数字,如果您的Feistel网络输出> Ncomb,则增加计数器并重试。这样可以覆盖整个字符串空间,但会拒绝无效的数字并必须重新执行算法。(但您不需要数据库来执行此操作。)
但是,除非你知道自己在做什么,否则不要涉足其中。
这些是用户密码吗?如果是,你需要考虑以下几点:
至于第二点,你可以使用LLNLLNLL作为密码模式(L表示字母,N表示数字),以避免这个问题。
如果你需要从25亿个密码中获取100万个密码,那么你肯定会在数据库中遇到冲突,因此你需要优雅地处理这些冲突。但是,如果你的随机数生成器足够强大,简单重试就足够了。
我认为你的ID数量在数万个范围内是安全的,即使超过这个数量,你也很可能没问题。
如果你想要一些确定性,你可以在一定次数的失败后强制更改密码。比如说,在50次失败后,你可以随机选择一个密码,并将其中一部分加1,直到找到一个可用的密码。
不过我敢打赌,在你的有生之年里,你永远不会看到这个额外功能被启用 :)
首先,您的需求列表并未说明字符串必须是随机的,因此您可以考虑使用数据库索引等其他方法。
如果“随机”是一个要求,您可以进行一些改进。
例如,如果我们有序列1、2、3、4、...并且使用循环二进制右移1位,它将变成4、1、5、2、...(假设我们只有3位)它不一定是一个位移,它可以是排列或任何其他“随机化”。
long bigrandom = ...;
int firstDigit = bigRandom % 10;
int secondDigit = ( bigrandom / 10 ) % 10;
等等。
然后,你只需要在数据库中存储随机数而不是字符串。由于字符串和数字之间存在一对一的关系,因此这并没有什么区别。
然而,当你尝试插入一个新值时,如果它已经在数据库中,你可以很容易地找到比最初生成的数字大的最小未分配数字,并使用那个数字代替你生成的数字。
通过这种方法,你可以保证相对快速地找到一个可用的代码,即使大多数代码已经被分配。
如果你需要更多的“代码”,只需生成更多的“随机”字符串并附加到表中即可。
我在你的需求中没有看到任何要求字符串必须是随机的。你可以像下面的伪代码一样做:
for letters in ( 'AAAAAA' .. 'ZZZZZZ' ) {
for numbers in ( 00 .. 99 ) {
string = letters + numbers
}
}
这将创建一个唯一的字符串,长度为八个字符,其中包含两个数字和六个大写字母。
如果您需要随机生成的字符串,则需要保留某种记录以跟踪先前生成的字符串,因此您需要访问数据库(或将它们全部保存在内存中,或将它们写入文本文件)并检查该列表。