这是一个家庭作业问题,但它只是一个更大项目的一小部分。其中一个限制是我们不允许出于任何原因使用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()的一些重要方面,我没有实现它。有没有更好的方法来解决这个问题?
答案 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()
的人。