C 创建一个小于最大给定值的随机数

C 创建一个小于最大给定值的随机数,c,random,C,Random,我想做的是创建一个函数,它接受一个参数,这个参数是随机生成应该创建的数量的限制。我曾经体验过,有些生成器只是一遍又一遍地重复生成的数字 如何制作一个不连续返回相同数字的生成器。有人能帮我实现我的目标吗 int randomGen(int max) { int n; return n; } 这个怎么样: int randomGen(int limit) { return rand() % limit; } /* ... */ int main() {

我想做的是创建一个函数,它接受一个参数,这个参数是随机生成应该创建的数量的限制。我曾经体验过,有些生成器只是一遍又一遍地重复生成的数字

如何制作一个不连续返回相同数字的生成器。有人能帮我实现我的目标吗

int randomGen(int max)
{
  int n;      
  return n;
}
这个怎么样:

 int randomGen(int limit)
 {
    return rand() % limit;

 }
   /* ... */
 int main()
 {
    srand(time(NULL));
    printf("%d", randomGen(2041));

    return 0;
  }

如果不明确了解您平台的随机生成器,不要do
rand()%max
。简单随机数生成器的低阶字节通常根本不是随机的

改为使用(返回一个介于最小值和最大值之间的数字):


更新:上述解决方案存在偏差(请参见注释以了解解释),可能不会产生统一的结果。我不会删除它,因为这是一个不应该做什么的非自然例子。请使用本线程其他地方推荐的拒绝方法。

任何伪随机生成器都会在一段时间内反复重复这些值。C只有
rand()。但你的平台可能比这更好


在POSIX系统上,您可以在
手册和48
页面中找到一整套功能。它们有一个明确的周期和质量。您可能会在那里找到您需要的。

rand
获得均匀分布结果的最简单方法如下:

int limited_rand(int limit)
{
  int r, d = RAND_MAX / limit;
  limit *= d;
  do { r = rand(); } while (r >= limit);
  return r / d;
}
结果将在
0
limit-1
的范围内,只要
0
RAND_MAX
的值与原始
RAND
函数具有相同的概率,每个结果都将以相同的概率出现

其他方法,如模运算或我使用的不带循环的除法引入了偏差。通过浮点中介的方法并不能避免这个问题。从
rand
中获取好的随机浮点数至少同样困难。如果您想要随机浮点数,使用my function for Integer(或其改进)是一个很好的起点

编辑:以下是我所说的偏见的解释。假设
RAND_MAX
为7,
limit
为5。假设(如果这是一个良好的
rand
函数)输出0、1、2、…、7的可能性相等。使用
rand()%5
将0、1、2、3和4映射到它们自己,但将5、6和7映射到0、1和2。这意味着值0、1和2弹出的可能性是值3和4的两倍。如果尝试重新缩放和分割,例如使用
rand()*(double)limit/(rand_MAX+1)
此处,0和1映射到0,2和3映射到1,4映射到2,5和6映射到3,7映射到4,则会出现类似现象


RAND_MAX
的大小在一定程度上减轻了这些影响,但如果
limit
很大,这些影响可能会回来。顺便说一句,正如其他人所说,对于线性同余PRNG(典型的
rand
实现),低位往往表现得非常糟糕,因此当
limit
是2的幂时,使用模运算可以避免我描述的偏差问题(因为
limit
在这种情况下通常平均除以
rand\u MAX+1
),但是你遇到了一个不同的问题。

这个常用方法是不正确的,并且会导致有偏随机数,除非
limit
是2的幂,OP没有提到每个数的ab相等概率的必要性。如果rand是线性同余生成器,即使极限是2的幂,它也会给出有偏差的结果。如果原始的
rand
有偏差,则修复该偏差要困难得多。。。你最好自己写。@R:LCG很差劲,但对于非科学应用程序,它们的高阶位性能也不错。但不是他们低阶的。@Matt:这很有效。根据rand()中的其他知识,我会用2的幂和拒绝来计算模。但是在这里,如果rand()是一个线性同余废话,没有更好的方法了。这个解决方案不能修复偏差。@R。很难得到一个在高阶项中有偏差的rand()实现。模量有问题,但这种方法没有。你在说什么偏差?如果
max-min
没有均匀地进入
RAND\u max+1
,一些输出将比其他输出有更多的输入映射到它们上。R是正确的,存在偏差。这是一个简单的鸽子洞原理问题-如果您尝试将每个可能的
rand()
值映射到一个输出整数上,并且可能的输出数不能精确地除以可能的
rand()
值,那么一些输出值将从比其他值更少的
rand()
值映射而来。因此,偏差。当然,如果
limit>RAND_MAX
,这将导致除以0。(但如果你不能从你想要的范围内得到统一的随机数,那也许是一件好事。)是的。。如果您担心可能真的发生这种情况,那么应该使用一个函数来包装
rand
,该函数可以多次调用
rand
,并附加位,直到在两个范围的已知固定幂上有一个均匀分布。
int limited_rand(int limit)
{
  int r, d = RAND_MAX / limit;
  limit *= d;
  do { r = rand(); } while (r >= limit);
  return r / d;
}