不使用cstdlib生成随机数?

时间:2017-11-08 23:56:09

标签: c++

这是一个家庭作业问题,但它只是一个更大项目的一小部分。其中一个限制是我们不允许出于任何原因使用STL。

我尝试使用ctime和递增修饰符汇总我自己的rand()函数。我认为即使它没有一致的种子,该函数也应该输出半随机数,只要它不是每秒多次输入相同的修饰符。

//notcstdlib.cpp
//<ctime> <cmath>
int rand(int mod)
{
    time_t seed;
    return std::abs(seed * mod);
}

但是这个示例代码

//main.cpp
#include "notcstdlib.h"
#include <iostream>

int main(int argc, char** argv)
{
    int f;
    for(int i = 1; i <= 10; i++)
    {
        f = rand(i);
        std::cout << "random num= " << f << "\n";
        std::cout << "rand % 10 = " << f%10 << "\n";
    }
    return 0;
}

始终返回7作为第一个值,并且每个其他数字只返回0到8之间的偶数。

//Output 1              //Output 2              //Output 3
random num= 134514987 | random num= 134514987 | random num= 134514987
rand % 10 = 7         | rand % 10 = 7         | rand % 10 = 7
random num= 13261304  | random num= 24238584  | random num= 27941368
rand % 10 = 4         | rand % 10 = 4         | rand % 10 = 8
random num= 19891956  | random num= 36357876  | random num= 41912052
rand % 10 = 6         | rand % 10 = 6         | rand % 10 = 2
random num= 26522608  | random num= 48477168  | random num= 55882736
rand % 10 = 8         | rand % 10 = 8         | rand % 10 = 6
random num= 33153260  | random num= 60596460  | random num= 69853420
rand % 10 = 0         | rand % 10 = 0         | rand % 10 = 0
random num= 39783912  | random num= 72715752  | random num= 83824104
rand % 10 = 2         | rand % 10 = 2         | rand % 10 = 4
random num= 46414564  | random num= 84835044  | random num= 97794788
rand % 10 = 4         | rand % 10 = 4         | rand % 10 = 8
random num= 53045216  | random num= 96954336  | random num= 111765472
rand % 10 = 6         | rand % 10 = 6         | rand % 10 = 2
random num= 59675868  | random num= 109073628 | random num= 125736156
rand % 10 = 8         | rand % 10 = 8         | rand % 10 = 6
random num= 66306520  | random num= 121192920 | random num= 139706840
rand % 10 = 0         | rand % 10 = 0         | rand % 10 = 0

显然我错过了rand()的一些重要方面,我没有实现它。有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

你永远不会初始化你的种子,试试

//notcstdlib.cpp
<ctime>
int rand(int mod)
{
    static time_t seed = time(NULL);
    return std::abs(seed * mod);
}

答案 1 :(得分:2)

您可能应该问您的老师是否也排除了std::rand()以及您是否真的需要实现自己的伪随机数生成器。或者更好的是,询问您是否允许使用<random>,以便您可以使用C ++的Mercene Twister引擎,这是一个非常好的伪随机数生成器。

如果你真的需要自己动手,std::rand()的最简单替代是LCG(线性同余发生器):

#define MY_RAND_MAX = 2147483647
static unsigned long my_rand_state = 1;

void my_srand(unsigned long seed)
{
    my_rand_state = seed;
}

long my_rand()
{
    my_rand_state = (my_rand_state * 1103515245 + 12345) % 2147483648;
    return my_rand_state;
}

然后,您可以分别使用my_srand()my_rand()MY_RAND_MAX std::srand()std::rand()RAND_MAX

// Seed it with the current time.
my_srand(std::time(nullptr));

// Print 1000 random numbers between 0 and MY_RAND_MAX.
for (int i = 0; i < 1000; ++i) {
    std::cout << my_rand() << ' ';
}
std::cout << '\n';

这会产生低质量的随机数(它们的分布很差。)请注意std::rand()也有不良分布。如果你想要高质量的随机数(意味着良好的分布),你应该使用C ++ <random>算法,使用std::mt19937引擎(这是Mercene Twister算法,它具有非常好的分布和巨大的时期。)

一般情况下,请避免rand()。请参阅Stephan T. Lavavej's 30min talk "rand() Considered Harmful",这是必须关注仍在其代码中使用rand()的人。