当用户在我的系统中添加新项目时,我想为该项目生成一个唯一的非递增伪随机7位数代码。创建的项目数量仅为数千(<10,000)。
因为它需要是唯一的,并且没有两个项目具有相同的信息,我可以使用哈希,但它需要是一个他们可以与其他人共享的代码 - 因此是7位数。
我最初的想法只是循环生成一个随机数,检查它是否已经使用过,如果是,请冲洗并重复。考虑到碰撞的可能性很小,我认为这是一个合理的解决方案。
对this question的回复建议生成所有未使用数字的列表并对其进行混洗。我可以在数据库中保留这样的列表,但是我们正在谈论10,000,000个条目,这些条目相对不常见。
有没有人有更好的方法?
答案 0 :(得分:15)
选择一个7位 prime 数字 A ,以及一个大 prime 数字 B ,并
int nth_unique_7_digit_code(int n) {
return (n * B) % A;
}
由此生成的所有唯一代码的计数将为 A 。
如果您想更加“安全”,请执行pow(some_prime_number, n) % A
,即
static int current_code = B;
int get_next_unique_code() {
current_code = (B * current_code) % A;
return current_code;
}
答案 1 :(得分:5)
您可以使用递增ID,然后将其与某个固定密钥进行异或。
const int XORCode = 12345;
private int Encode(int id)
{
return id^XORCode;
}
private int Decode(int code)
{
return code^XORCode;
}
答案 2 :(得分:4)
老实说,如果你只想生成几千个7位代码,而1000万个不同代码可用,我认为只生成一个随机代码并检查碰撞就足够了。
在最糟糕的情况下,第一次命中碰撞的几率大约是千分之一,并且只需生成一个新的7位数代码并再次检查碰撞的计算工作量就会小得多而不是保留字典或类似的解决方案。
使用GUID代替7位代码作为建议的结果肯定也会有效,但当然GUID对于用户来说会稍微难以记住。
答案 3 :(得分:2)
我建议使用guid而不是7位代码,因为它会更独特,你不必担心生成它们,因为.NET会为你做这件事。
答案 4 :(得分:2)
“唯一”ID的所有解决方案都必须在某处包含数据库:包含已使用ID的一个或包含免费ID的一个。正如您所注意到的,具有可用ID的数据库将非常大,因此大多数情况下,人们使用“已使用的ID”数据库并检查冲突。
也就是说,有些数据库提供了一个“随机ID”生成器/序列,它已经以随机顺序返回一个范围内的ID。
这可以通过使用随机数生成器来实现,该生成器可以创建范围内的所有数字而无需重复自身以及可以将其状态保存在某处的功能。所以你要做的就是运行一次生成器,使用ID并保存新状态。对于下一次运行,您加载状态并将生成器重置为最后一个状态以获取下一个随机ID。
答案 5 :(得分:2)
我假设您将拥有生成的表格。在这种情况下,我没有看到挑选随机数并在数据库中检查它们的问题,但我不会单独进行。生成它们很便宜,相对于此,DB查询的代价很高。我一次生成100或1,000,然后询问DB中哪些存在。打赌你大部分时间都不需要做两次。
答案 6 :(得分:2)
您有&lt; 10.000项,因此您只需要4位数就可以存储所有项目的唯一编号。 由于您有7位数字,因此您有3位数字。
如果您将4位数的唯一序列号与3位数的随机数组合在一起,您将是唯一且随机的。您可以使用生成的每个新ID递增序列号。
您可以按任意顺序附加它们,也可以将它们混合。
seq = abcd, rnd = ABC
您可以创建以下ID:
如果您只使用一种混合算法,您将拥有看起来随机的唯一数字。
答案 7 :(得分:1)
我会尝试使用LFSR(线性反馈移位寄存器)代码非常简单,您可以在任何地方找到示例Wikipedia,即使它不是加密安全的,它看起来非常随机。此外,实施将非常快,因为它主要使用移位操作。
答案 8 :(得分:0)
数据库中只有数千个项目,您的原始想法似乎很合理。检查几万个项目的已排序(索引)列表中的值的存在只需要进行一些数据提取和比较。
预先生成列表听起来不是一个好主意,因为你要么存储的数量超过了必要的数量,要么你将不得不处理它们的用完。
答案 9 :(得分:0)
击中的可能性非常低 例如 - 您有10 ^ 4个用户和10 ^ 7个可能的ID 你在行中选择使用ID 10次的概率现在是10 ^ -30 这个机会在任何人的一生中都低于一次。
答案 10 :(得分:0)
好吧,你可以要求用户选择他们自己的7位数字并根据现有数字(你在用完时存储的数量)对其进行验证,但我怀疑你会过滤很多1234567,7654321,9999999,7777777类型的响应,可能需要一些RegEx来实现过滤,而且你必须警告用户不要这样的序列,以免有一个坏的,重复的用户输入经验。