我必须为3种不同的病例生成随机数。 一世。 1个骰子 II。一对骰子 III。 3个骰子 我的问题: 1.请建议我使用良好的逻辑来为所有3个案例生成随机数。 2.当我考虑2个骰子而不是1个时,逻辑会改变吗? 3.我们必须生成一个随机数的范围会影响随机函数的逻辑吗?
答案 0 :(得分:5)
如果范围足够小,那么在使用通常的模数方法
时应该没有问题int GetRandomInt(int Min, int Max)
{
return (rand()%(Max-Min+1))+Min;
}
(Min
一个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()
范围的后三分之一。
这对你意味着什么?
可能没什么。如果你想做的只是一个骰子滚动模拟器,你可以毫无问题地使用modulo方法,因为涉及的范围很小,而第二个问题,尽管仍然存在,它几乎无关紧要:假设您的范围是3且MAX_RAND
32767:从0到32765,0,1和2具有相同的概率,但是上升到32767 0和1获得一个潜在的退出,这几乎是不相关的,因为它们通过从完美的1/3(10922/32766 = 0,333 ......)概率到每个1到10922/32767为2(~0,33332)和10923/32767(~0,33335)为0和1(假设rand()
提供完美分发。
无论如何,为了克服这些问题,一个非常常用的方法是使用这样的方法在更宽的范围内“拉伸”rand()
范围(或将其压缩到更小的范围):
int GetRandomInt(int Min, int Max)
{
return (int)(((double)rand())/MAX_RAND*(Max-Min))+Min;
}
基于等价rand():MAX_RAND=X:(Max-Min)
。转换为double是必要的,否则rand()
与其最大值之间的整数除法将始终为0(或在rand()==MAX_RAND
的罕见情况下为1);如果MAX_RAND很小且范围也不太宽,则可以在执行产品的整数运算中完成,否则存在溢出的高风险。
我怀疑,如果输出范围大于rand()
的范围,“拉伸”和fp值截断(由于转换为int)会以某种方式影响分布,但只是本地(例如,在小范围内,您可能永远不会获得某个数字,但在全球范围内,分布看起来会很好。)
请注意,此方法有助于克服C标准库随机数生成器的扩散限制,即返回值的低位的低随机性 - 顺便提一下,当您执行模数运算,输出范围小。
但是,请记住,C标准库RNG是一个简单的,它努力遵守“简单”的统计规则,因此很容易预测;当需要“严重”的随机数时(例如加密),不应该使用它。对于这样的需求,有专门的RNG库(例如GNU科学库的RNG part),或者,如果你需要真正随机的东西,有几个真正的随机数服务(其中最着名的是this),它不使用数学伪RNG,而是从真实的随机源(例如放射性衰变)中获取它们的数字。
答案 1 :(得分:2)
是的,就像DarkDust说的那样,这听起来像是家庭作业,所以,为了回答你的问题,我会说:
--> No, the logic doesnt not change, no matter how many dices you include.
--> Easiest way to do this would be, just make a function that give you ONE
random function, and depending on how many dices you have, call it that
many times.
--> You can instead include for loop in the function and add the values into
array and return the array.
这样,您也可以为100个骰子生成随机数。
答案 2 :(得分:1)
因为这听起来像是家庭作业,所以我只是给你一些“足够好”的提示(专业人士会略有不同):使用random()
函数和%
(模数)运算符。模数是分裂后的“提醒”。