unsigned const number = minimum + (rand() % (maximum - minimum + 1))
我知道如何(轻松)生成0到100范围内的随机数。但int
的全范围中的随机数呢(假设{ {1}}),即sizeof(int) == 4
到INT_MIN
,包括哪个?
我不需要这个用于加密等,但是大致均匀的分布会很好,我需要很多这些数字。
我目前使用的方法是生成0到255(含)范围内的4个随机数,并进行一些混乱的转换和位操作。我想知道是否有更好的方式。
答案 0 :(得分:4)
在我的系统RAND_MAX
上是32767,即15位。因此,对于32位unsigned
,只需调用三次并移位,或者屏蔽等。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
unsigned rando, i;
srand((unsigned)time(NULL));
for (i = 0; i < 3; i++) {
rando = ((unsigned)rand() << 17) | ((unsigned)rand() << 2) | ((unsigned)rand() & 3);
printf("%u\n", rando);
}
return 0;
}
节目输出:
3294784390
3748022412
4088204778
答案 1 :(得分:1)
作为参考,我正在添加我一直在使用的内容:
int random_int(void) {
assert(sizeof(unsigned int) == sizeof(int));
unsigned int accum = 0;
size_t i = 0;
for (; i < sizeof(int); ++i) {
i <<= 8;
i |= rand() & 0x100;
}
// Attention: Implementation defined!
return (int) accum;
}
但我更喜欢Weather Vane的解决方案,因为它使用较少的rand()
次调用,从而更多地利用了它产生的(希望是好的)分布。
答案 2 :(得分:0)
我们应该能够通过累积足够的位来填充给定类型,无论rand()
的范围是什么,或者我们正在寻找什么尺寸的结果,我们都应该做一些有用的事情:
// can be any unsigned type.
typedef uint32_t uint_type;
#define RAND_UINT_MAX ((uint_type) -1)
uint_type rand_uint(void)
{
// these are all constant and factor is likely a power of two.
// therefore, the compiler has enough information to unroll
// the loop and can use an immediate form shl in-place of mul.
uint_type factor = (uint_type) RAND_MAX + 1;
uint_type factor_to_k = 1;
uint_type cutoff = factor ? RAND_UINT_MAX / factor : 0;
uint_type result = 0;
while ( 1 ) {
result += rand() * factor_to_k;
if (factor_to_k <= cutoff)
factor_to_k *= factor;
else
return result;
}
}
注意:使填充所有位所需的最小呼叫数为rand()
。
让我们verify给出统一的分布。
此时我们可以将rand_uint()
的结果转换为类型 int 并完成,但是在指定范围内输出更有用。问题是:当操作数类型为 int 时,我们如何到达INT_MAX
?
int uniform_int_distribution(int min, int max)
{
// [0,1) -> [min,max]
double canonical = rand_uint() / (RAND_UINT_MAX + 1.0);
return floor(canonical * (1.0 + max - min) + min);
}
作为最后一点,可能值得用类型 double 来实现随机函数,即为DBL_MANT_DIG
积累足够的位并返回范围< EM> [0,1)。实际上这就是std::generate_canonical
的作用。