描述:我们正在为应用程序构建新版本,该版本在Sqlite数据库中维护记录。在我们应用程序的上一个版本中,每个记录没有唯一的键。但是现在,随着新升级版本的推出,我们需要支持从旧版本的数据库中导入数据。因此,我们读取旧数据库中的每条记录并为其生成一个随机数作为唯一键,并将其存储在新数据库中。在这里,我们可能需要连续导入多达10000条记录。
好的,最终你要么必须停止生成它们,要么就会开始重复它们。
在计算机上,您的选择相当有限,只能使用伪随机数生成器(PRNG),鉴于您的约束条件是它们永远不会重复,因此PRNG是您的最佳选择 - 真正的随机数据偶尔会重复一个数字。
在您的情况下,我建议使用大型PRNG(32位或更大)来洗牌您的10,000个数字,然后按洗牌顺序发送数字。
一旦使用完毕,您可以再次洗牌 - 由于PRNG非常大,您可以在重复一个序列之前多次遍历这10k个数字。
给我们更多关于您正在做什么的信息,我们可能会想出更好的答案。
-Adam
Mersenne Twister是当前最好的(虽然可能比一些真正新的发现晚了几周)。 几乎每种语言的源代码都可以在某个地方找到,MT也在Boost 这里提供。
如果你的编译器支持,TR1具有良好的随机数支持。
否则,可以使用Boost。
基本上它就是成为TR1的东西。
至于避免重复 - 你需要一个洗牌。它可能很简单,但如果不正确地执行,就会有一些陷阱。Jeff Atwood在一段时间前写过一个很好的文章:
Boost可能做了一些保证不重复数字的事情。
但为了有趣,这是我的想法。
注意:我没有尝试在那个方向上生成我的随机数,那会导致疯狂。
#include <iostream>
#include <vector>
#include <algorithm>
class GaranteedNoRepeatRandom
{
public:
GaranteedNoRepeatRandom(int limit)
:data(limit)
,index(0)
{
for(int loop=0;loop < limit;++loop)
{ data[loop] = loop;
}
// Note: random_shuffle optionally takes a third parameter
// as the rand number generator.
std::random_shuffle(&data[0],&data[0]+limit);
}
unsigned int rand()
{
unsigned int result = data[index];
index = (index+1) % data.size();
// Add code to re-shuffle after index wraps around
return result;
}
private:
std::vector<unsigned int> data;
std::vector<unsigned int>::size_type index;
};
int main()
{
GaranteedNoRepeatRandom gen(10000);
for(int loop =0;loop < 10;++loop)
{
std::cout << gen.rand() << "\n";
}
}
随机性的程度如何?显然有rand(),此外还有特定于操作系统的内容(例如Windows中的CryptoAPI)。你是在编写某些东西(不建议),还是只是寻找一个现有的函数来使用?
对于使用随机数作为数据库记录的唯一键是否合适这个想法,您是否可以进行质疑?我不熟悉SQLite,但值得调查它是否支持某种内部唯一列标识符。例如,SQL Server有“identity”列,Oracle有“sequences”,两者都具有相同的目的。