编写 ac 函数,在给定特定范围的情况下生成一个随机数、一对随机数或一组随机数
我必须为 3 种不同的情况生成随机数。 我。 1 个骰子 二.一对骰子 三. 3 个骰子 我的问题: 1.请建议我为所有 3 种情况生成随机数的良好逻辑。 2.当我考虑2个骰子而不是1个骰子的cses时,逻辑会改变吗? 3.我们生成随机数的范围对随机函数的逻辑有多大影响?
i have to generate random numbers for 3 different cases.
i. 1 dice
ii. a pair of dice
iii. 3 dices
my questions:
1. please suggest me sm good logic to generate random numbers for all the 3 cases.
2. does the logic change when i consider the cses of 2 dices, rather than 1?
3.how much of an effect does the range in which we have to genrate a random number affect the logic of the random function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果范围足够小,那么使用通常的取模方法应该不会有问题
(其中
Min
和Max
指定一个闭区间,[Min
code>,Max
])并为每次掷骰子调用一次。不要忘记在应用程序开始时调用 srand(time(NULL))(仅在开始时调用,而不是每次您想要获取随机数时)为随机数生成器提供种子。
如果范围开始变大,你可能要面临两个问题:
首先,
rand()
的范围显然不是[0, +∞),而是[0,RAND_MAX
],其中RAND_MAX
是保证至少为 32767 的#define
。如果您的范围 (Max-Min
) 跨越超过RAND_MAX
,那么,使用此方法,您将得到一些返回概率为零的数字。这更微妙:假设
RAND_MAX
大于您的范围,但没有更大,假设RAND_MAX==1.5*/(Max-Min)
。在这种情况下,结果的分布不会均匀:
rand()
返回 [0,RAND_MAX
] 范围内的一个整数(并且该范围内的每个整数应该是等概率的),但是你用(Max-Min)
来取除法的其余部分。这意味着所需范围前半部分的数字被返回的概率是其他数字的两倍:它们实际上可以来自rand() 的前和第三个三分之一
范围,而所需范围的后半部分只能来自rand()
范围的第二个三分之一。这对你来说意味着什么?
可能什么也没有。如果您想做的只是一个掷骰子模拟器,那么使用取模方法就不会出现任何问题,因为涉及的范围很小,而第二个问题尽管仍然存在,但几乎无关紧要:假设你的范围是 3 和 MAX_RAND 32767:从 0 到 32765,0、1 和 2 具有相同的概率,但直到 32767 0 和 1 获得一个潜在的退出,这几乎是无关的,因为它们从每个 1 的完美 1/3 (10922/32766=0,333...) 概率转变为 2 (~0,33332) 的 10922/32767 和 0 和 1 的 10923/32767 (~0,33335) (假设
rand()
提供完美分布)。无论如何,为了克服这些问题,一个常用的方法是使用如下方法将
rand()
范围“拉伸”到更宽的范围(或将其压缩到更小的范围):基于等价
rand():MAX_RAND=X:(最大-最小值)
。转换为 double 是必要的,否则rand()
与其最大值之间的整数除法将始终产生 0(或者在rand()==MAX_RAND
的罕见情况下产生 1) >);如果 MAX_RAND 很小并且范围也不是太宽,可以用整数运算来先执行乘积,否则溢出的风险很高。我怀疑,如果输出范围大于 rand() 的范围,“拉伸”和 fp 值截断(由于转换为 int)会以某种方式影响分布,但是仅在本地(例如,在小范围内,您可能永远不会得到某个数字,但在全球范围内,分布看起来不错)。
请注意,此方法有助于克服 C 标准库随机数生成器的分散限制,即返回值的低位随机性较低 - 顺便说一句,这些位是您在执行模运算时使用的那些输出范围小。
然而,请记住,C 标准库 RNG 是一个简单的库,它努力遵守“简单”的统计规则,因此很容易预测;当需要“严重”随机数时(例如密码学),不应该使用它。对于此类需求,有专用的 RNG 库(例如 RNG 部分GNU 科学图书馆的 ),或者,如果您需要真正随机的东西,有几种真正随机数服务(最著名的之一是this),不使用数学伪 RNG,而是从真正的随机源(例如放射性衰变)。
If the range is small enough, you shouldn't have problems in using the usual modulo method
(where
Min
aMax
specify a closed interval, [Min
,Max
])and calling it once for each dice roll. Don't forget to call
srand(time(NULL))
at the start of the application (at the start only, not each time you want to get a random number) to seed the random number generator.If the range starts to be bigger, you may have to face two problems:
First, the range of
rand()
obviously isn't [0, +∞), instead it's [0,RAND_MAX
], whereRAND_MAX
is a#define
guaranteed to be at least 32767. If your range (Max-Min
) spans overRAND_MAX
, then, with this method, you'll have some numbers that will have a zero probability of being returned.This is more subtle: suppose that
RAND_MAX
is bigger than your range, but not that bigger, let's say thatRAND_MAX==1.5*/(Max-Min)
.In this case, the distribution of results won't be uniform:
rand()
returns you an integer in the range [0,RAND_MAX
] (and each integer in this range should be equiprobable), but you are taking the rest of the division with(Max-Min)
. This means that the numbers in the first half of your required range have twice the probability of being returned than the others: they can actually come from the first and the third third of therand()
range, while the second half of the required range can come only from the second third of therand()
range.What does this mean for you?
Probably nothing. If all you want to do is a dice-roll simulator, you can go without problems with the modulo method, since the range involved is small, and the second problem, despite being still present, it's almost irrelevant: suppose your range is 3 and
MAX_RAND
32767: from 0 to 32765, 0, 1 and 2 has the same probability, but going up to 32767 0 and 1 gain one potential exit, which is almost irrelevant, since they pass from a perfect 1/3 (10922/32766=0,333...) probability for each one to a 10922/32767 for 2 (~0,33332) and 10923/32767 (~0,33335) for 0 and 1 (assuming thatrand()
provides a perfect distribution).Anyhow, to overcome such problems a quite used method is to "stretch" the
rand()
range over a wider range (or compressing it to a smaller range) using a method like this:based on the equivalence
rand():MAX_RAND=X:(Max-Min)
. The conversion to double is necessary, otherwise the integer division betweenrand()
and its maximum value will always yield 0 (or 1 in the rare case ofrand()==MAX_RAND
); it could be done in integer arithmetic performing the product first if MAX_RAND is small and the range too is not too wide, otherwise there's a high risk of overflow.I suspect that, if the output range is bigger than the range of
rand()
, the "stretching" and the fp value truncation (due to the conversion to int) affect in some way the distribution, but just locally (e.g. in small ranges you may never get a certain number, but globally the distribution will look ok).Notice that this method helps to overcome to a diffused limitation of the C standard library random number generator, i.e. the low randomness of the lower bits of the returned value - which are, incidentally, the ones you are using when you perform a modulo operation with a small output range.
However, keep in mind that the C standard library RNG is a simple one, that strives to comply with "easy" statistical rules, and as such is easily predictable; it shouldn't be used when "serious" random numbers are required (e.g. cryptography). For such needs there are dedicated RNG libraries (e.g. the RNG part of the GNU Scientific Library), or, if you need really random stuff, there are several real random number services (one of the most famous is this), which do not use mathematical pseudo-RNG, but take their numbers from real random sources (e.g. radioactive decay).
是的,就像 DarkDust 所说,这听起来像是家庭作业,所以,为了回答你的问题,我会说:
这样,你也可以为 100 个骰子生成随机数。
Yea, like DarkDust said, this sounds like homework, so, to answer your questions with that in mind, I'd say:
This way, you can generate random number for 100 dices too.
因为这听起来像是家庭作业,所以我只是给出一些对你来说应该“足够好”的提示(专业人士的做法略有不同):使用
random()
函数和%
(模)运算符。 Modulo 是除法之后的“提醒”。Since this sounds like homework I'm just going to give hints which should be "good enough" for you (a pro would do it slightly differently): use the
random()
function and the%
(modulo) operator. Modulo is the "reminder" after a division.