wor*_*wiz 2 c random function conceptual
我必须为3个不同的案例生成随机数.一世.1个骰子ii.一对骰子iii.3我的问题:1.请建议我为所有3个案例生成随机数的良好逻辑.2.当我考虑2个骰子而不是1个时,逻辑会改变吗?3.我们必须生成一个随机数的范围会影响随机函数的逻辑吗?
如果范围足够小,则在使用通常的模数方法时应该没有问题
int GetRandomInt(int Min, int Max)
{
return (rand()%(Max-Min+1))+Min;
}
Run Code Online (Sandbox Code Playgroud)
(其中Mina Max指定一个封闭的区间,[ Min,Max])
并为每个骰子掷骰子调用一次.不要忘记srand(time(NULL))在应用程序开始时调用(仅在开始时调用,而不是每次都要获取随机数)来为随机数生成器播种.
如果范围开始变大,您可能不得不面临两个问题:
首先,范围rand()显然不是[0,+∞),而不是它的[0 RAND_MAX],其中RAND_MAX是#define保证至少32767如果你的范围(Max-Min)跨越RAND_MAX,那么,用这种方法,你会有一些数字将返回零概率.
这是更微妙的:假设它RAND_MAX比你的范围大,但不是那么大,让我们说RAND_MAX==1.5*/(Max-Min).在这种情况下,结果的分布将不一致:rand()返回范围为[0,RAND_MAX]的整数(并且此范围内的每个整数应该是等概率的),但是您将使用除法的其余部分(Max-Min).这意味着你所需范围的前半部分中的数字的返回概率是其他数字的两倍:它们实际上可以来自范围的第一个和第三个三分之一rand(),而所需范围的后半部分只能来自从rand()范围的第二个三分之一.
这对你意味着什么?
可能没什么.如果你想做的只是一个骰子滚动模拟器,你可以毫无问题地使用模数法,因为所涉及的范围很小,而第二个问题,尽管仍然存在,它几乎无关紧要:假设你的范围是3和MAX_RAND32767:从0到32765,0,1和2具有相同的概率,但是上升到32767 0和1获得一个潜在的退出,这几乎是不相关的,因为它们从完美的1/3传递(10922/32766 = 0,333) ...)对于0和1(假设rand()提供完美分布),每个对于2(~0,33332)和10923/32767(~0,33335)的10922/32767的概率.
无论如何,为了克服这些问题,一种非常常用的方法是使用如下方法rand()在更宽的范围内"拉伸" 范围(或将其压缩到更小的范围):
int GetRandomInt(int Min, int Max)
{
return (int)(((double)rand())/MAX_RAND*(Max-Min))+Min;
}
Run Code Online (Sandbox Code Playgroud)
基于等价rand():MAX_RAND=X:(Max-Min).转换为double是必要的,否则整数除以rand()及其最大值将始终为0(或在极少数情况下为1 rand()==MAX_RAND); 如果MAX_RAND很小且范围也不太宽,则可以在执行产品的整数运算中完成,否则存在溢出的高风险.
我怀疑,如果输出范围大于范围rand(),"拉伸"和fp值截断(由于转换为int)会以某种方式影响分布,但只是局部影响(例如,在小范围内,您可能永远不会得到一定数量,但全球分布看起来还不错).
请注意,此方法有助于克服C标准库随机数生成器的扩散限制,即返回值的低位的低随机性 - 顺便提一下,当您执行模运算时使用的那些输出范围小.
但是,请记住,C标准库RNG是一个简单的,它努力遵守"简单"的统计规则,因此很容易预测; 当需要"严重"随机数时(例如加密),不应使用它.对于这样的需求,有专门的RNG库(例如GNU科学库的RNG部分),或者,如果你需要真正随机的东西,有几个真正的随机数服务(其中最着名的是这个),它们不使用数学伪RNG,但从真实的随机源(例如放射性衰变)中获取它们的数字.
| 归档时间: |
|
| 查看次数: |
3474 次 |
| 最近记录: |