我需要一个能在给定范围内生成随机整数的函数(包括边界值).我没有不合理的质量/随机性要求,我有四个要求:
我目前有以下C++代码:
output = min + (rand() * (int)(max - min) / RAND_MAX)
Run Code Online (Sandbox Code Playgroud)
问题是,它并不是真正统一的 - 只有当rand()= RAND_MAX时才返回max(对于Visual C++,它是1/32727).这是小范围的主要问题,如<-1,1>,其中最后一个值几乎从不返回.
所以我抓住笔和纸,并提出了以下公式(它建立在(int)(n + 0.5)整数舍入技巧):

但它仍然没有给我统一的分配.对于值-1,0,0,重复运行10000个样本给出37:50:13的比率.
你能建议更好的配方吗?(甚至整个伪随机数发生器功能)
在这个StackOverflow问题中:
接受的答案表明以下公式用于生成给定min和之间的随机整数max,min并且max包含在范围内:
output = min + (rand() % (int)(max - min + 1))
Run Code Online (Sandbox Code Playgroud)
但它也说
这仍然略微偏向较低的数字......也可以扩展它以消除偏差.
但这并没有解释为什么它偏向于较低的数字或如何消除偏见.因此,问题是:这是在(签名)范围内生成随机整数的最佳方法,而不依赖于任何花哨的东西,只是rand()功能,如果它是最优的,如何消除偏差?
编辑:
我刚刚测试了while@Joey建议的-loop算法对浮点外推:
static const double s_invRandMax = 1.0/((double)RAND_MAX + 1.0);
return min + (int)(((double)(max + 1 - min))*rand()*s_invRandMax);
Run Code Online (Sandbox Code Playgroud)
看看有多少均匀的"球""落入"并分布在许多"桶"中,一个用于浮点外推,另一个用于while-loop算法.但结果根据"球"(和"桶")的数量而变化,所以我不能轻易选择胜利者.可以在此Ideone页面找到工作代码.例如,对于10个桶和100个球,对于浮点外推,桶中理想概率的最大偏差小于while-loop算法(分别为0.04和0.05),但是有1000个球,while-loop 的最大偏差算法较小(0.024和0.011),对于10000个球,浮点外推再次做得更好(0.0034和0.0053),依此类推,没有太多的一致性.考虑到没有一种算法能够比其他算法更好地一致地产生均匀分布的可能性,使得我倾向于浮点外推,因为它似乎比while-loop算法执行得更快.那么选择浮点外推算法还是我的测试/结论不完全正确呢?
我有一个启动许多客户端进程的bash脚本.这些是人工智能游戏玩家,我用它来测试与许多玩家的游戏,大约有400个连接.
我遇到的问题是AI播放器使用的问题
srand( time(nullptr) );
Run Code Online (Sandbox Code Playgroud)
但是如果所有玩家大约在同一时间开始,他们将经常收到相同的time()值,这意味着他们都在同一个rand()序列中.
测试过程的一部分是确保如果大量客户端几乎同时尝试连接,服务器就可以处理它.
我考虑过使用类似的东西
srand( (int) this );
Run Code Online (Sandbox Code Playgroud)
或类似的,基于每个实例都有唯一内存地址的想法.
还有另一种更好的方法吗?