如何用c ++改进这个随机数生成器代码?

时间:2016-01-30 04:33:28

标签: c++ c++11 shuffle random-seed

我是C ++学生,我正在创建一个随机数生成器。

事实上我应该说我的算法选择一个定义范围内的数字。

我写这篇文章只是因为我的好奇心。

我没有质疑现有的库函数。

在编写基于随机性的应用程序时,我总是使用库函数,但我再次声明我只是想因为我的好奇而制作它。

我还想知道我的算法或方法是否有问题。 因为我搜索了PRNG的工作方式,并且在一些网站上他们说数学算法就在那里,预定义的一系列数字和一个种子只是将指针设置在系列中的不同点上,并且在一些时间间隔之后,序列会自行重复。

我的算法刚开始在可能值的数组中来回移动,种子每次都会以不同的值打破循环。我不认为这种做法是错误的。我得到的答案建议使用不同的算法,但他们没有解释我当前的算法有什么问题?

是的,我的种子存在问题,因为它不准确,结果很难预测,如下所示: -

  

COUT<   <   RN(50100);

四次跑步的结果是74,93,56,79。

查看"增加顺序的模式"。

对于大范围的模式可以很容易看到。我得到了一个关于获得好种子的答案,但是这也推荐了一种新的算法(但没有说出原因?)。

另一种方法可能是每次随机生成一个新序列来重新排列我的数组。增加顺序的模式将会消失。重新安排的任何帮助也将是好的。这是下面的代码。如果我的话功能不可以请通知我。

在期待中感谢你。

int rn(int lowerlt, int upperlt)
{
    /* Over short ranges, results are satisfactory.
     * I want to make it effective for big ranges.
     */

    const int size = upperlt - lowerlt; // Constant size of the integer array.

    int ar[size]; // Array to store all possible values within defined range.
    int i, x, ret; // Variables to control loops and return value.
    long pointer = 0; //pointer variable. The one which breaks the main loop.


    // Loop to initialize the array with possible values..
    for (i=0, x=lowerlt; x <= upperlt; i++, x++)
        ar[i]=x;

    long seed = time(0);

    //Main loop . To find the random number.
    for (i=0; pointer <= seed; i++, pointer++)
    {
        ret = ar[i];
        if (i == size-1)
        {
            // Reverse loop.
            for (; i >= 0; i--)
            {
                ret=ar[i];
            }
        }
    }

    return ret;
}

2 个答案:

答案 0 :(得分:0)

警告:从您的帖子中,除了您的随机生成器算法之外,您的一个问题是获得良好的种子价值,因此我将解决其中的这一部分。

您可以使用/dev/random获取种子值。这将是一个很好的起点[并且本身就足够了],但可能会被认为是&#34;作弊&#34;从某种角度来看。

所以,这里有一些其他来源&#34; entropy&#34;:

使用更高分辨率的时钟来源:gettimeofdayclock_gettime(CLOCK_REALTIME,...)将其称为&#34; cur_time&#34;。分别仅使用微秒或纳秒部分,称之为&#34; cur_nano&#34;。请注意,cur_nano本身通常非常随机。

getpid(2)。这有几个不可预测的位,因为在调用其他程序之间,我们不知道有多少。

创建一个新的临时文件并获取文件的inode编号[然后将其删除]。这随时间变化缓慢。每次调用时都可能相同[或不]

获取系统启动时系统时钟的高分辨率值,并将其命名为&#34; sysboot&#34;。

获取&#34;会话的开始时间的高分辨率值&#34;:当您的程序的父shell启动时,将其命名为&#34; shell_start&#34;。

如果您使用的是Linux,则可以计算/proc/interrupts的校验和,因为它总是在变化。对于其他系统,获取各种类型的中断数量的哈希[应该可以从某种类型的系统调用中获得]。

现在,创建一些上述所有的哈希值(例如):

dev_random * cur_nano * (cur_time - sysboot) * (cur_time - shell_start) *
getpid * inode_number * interrupt_count

这是一个简单的等式。您可以通过一些XOR和/或sum操作来增强它。进行实验,直到找到适合你的方式。

注意:这只会为您提供PRNG的种子值。您必须从其他内容创建PRNG(例如,伯爵的线性算法)

答案 1 :(得分:0)

unsigned int Random::next() {
    s = (1664525 * s + 1013904223);
    return s;
}
随着该功能的每次调用,

's'正在增长。 正确是

unsigned int Random::next() {
   s = (1664525 * s + 1013904223) % xxxxxx;
   return s;
}

也许使用此功能

long long Factor = 279470273LL, Divisor = 4294967291LL;
long long seed;
next()
{
    seed = (seed * Factor) % Divisor;
}