C++中的开源随机数生成算法

Open source random number generation algorithm in C++?

本文关键字:算法 随机数 开源 C++      更新时间:2023-10-16

我需要在没有重复的情况下连续生成1-10000范围内的随机数。有什么建议吗?

描述:我们正在为我们的应用程序构建一个新版本,它在SqliteDB中维护记录。在应用程序的上一个版本中,我们没有为每个记录设置唯一的密钥。但现在有了新的升级版本,我们需要支持从上一个版本的DB导入功能。因此,我们所做的是,从旧数据库中读取每一条记录,并为唯一密钥生成一个随机数,并将其存储在新数据库中。在这里,我们需要连续导入多达10000条记录。

好吧,最终你要么必须停止生成它们,要么你将以星形复制它们。

在计算机上,您的选择非常局限于伪随机数生成器(PRNG),并且考虑到它们永远不会重复的限制,那么PRNG是您的最佳选择-真实随机数据偶尔会重复一个数字。

在你的情况下,我会考虑使用一个大的PRNG(32位或更大)来打乱你的10000个数字,然后按照打乱的顺序发送数字。

一旦它们用完,你可以再次洗牌——因为PRNG太大了,你可以在复制序列之前多次遍历10k个数字。

给我们更多关于你在做什么的信息,我们可能会给出更好的答案。

-Adam

Mersenne Twister是目前最好的(尽管我可能会比任何真正的新发现晚几周)。几乎每种语言的源代码都有,Boost中也提供了MT。

如果它真的必须在1到100000的范围内,没有重复,但不是顺序的,那么最好先创建一个10000个元素的顺序数组,然后对它们进行混洗。

然而,我必须同意对原问题的评论。我认为让它们不按顺序排列没有任何价值。

或者,在unique&非连续性很重要,那么1到10000的范围就成了问题。最好只使用GUID。

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";
    }
}

TR1具有良好的随机数支持-如果您的编译器支持的话。

否则提升

这基本上就是后来的TR1。

至于不重复-您需要洗牌。这可能很简单,但如果你做得不对,也会有一些陷阱。Jeff Atwood不久前写了一篇很好的文章:

http://www.codinghorror.com/blog/archives/001015.html

BoostRandom是一个不错的选择,对我来说效果很好。但是,如果你不需要很多随机数生成器和发行版,你可以寻找另一个库,只是不安装整个Boost包。

随机性如何?显然,有rand(),也有特定于操作系统的东西(例如,Windows在CryptoAPI中有一些东西)。你是在写一些东西(不推荐),还是只是在寻找一个预先存在的函数来使用?

mtrand很不错。

可以质疑使用随机数作为数据库记录的唯一密钥的整个想法吗?我不熟悉sqlite,但值得研究一下它是否在内部支持某种唯一的列标识符。例如,SQL Server有"identity"列,Oracle有"sequences"列,这两个列的作用相同。

生成大的随机数。说128位。在一组10000中,两个这样的数字相同的几率小得离谱(大约为n^2/2^b,其中n=所需数字的数量,b=所用比特的数量)。给定足够的比特,几率会变得比你的公羊被宇宙射线破坏的几率更小,这样你的算法无论如何都会失败。请注意,从中绘制随机数的空间确实有您要查找的位数。很容易从32位的池中错误地生成128位的数字(即,即使生成数字1到2^128,也只有2^32种可能性)。boost库中的随机数生成器可以为您正确地执行此操作。BTW:如果你不喜欢128位,那么就使用256位或更多,直到你确信不存在哈希冲突的实际可能性。如果你只需要做一次,那么就使用前面回答中提到的shuffle方法。这将具有生成完美哈希的优势。

虽然您可能需要生成一个不重复的值序列,但不能将结果称为"随机"。真正的随机性与其说与缺乏重复有关,不如说与序列中值的分布有关。

随机数的生成太重要了,不能让它成为偶然。--Robert R.Coveyou,橡树岭国家实验室

C中的数字配方有一整章专门讨论随机数生成。这里有一些实现。从简单直接到具有良好统计特性的复杂。

http://random.org/如果您需要真正的随机数