Andrew Koenig的Accelerated C++问题 7-9 提问:
7-9。(困难)第 7.4.4/135 节中的 nrand 实现不适用于大于 RAND_MAX 的参数。通常,这个限制没有问题,因为无论如何 RAND_MAX 通常是最大可能的整数。尽管如此,在某些实现中 RAND_MAX 远小于最大可能的整数。例如,RAND_MAX 为 32767 (2^15 -1) 并且最大可能的整数为 2147483647 (2^31 -1) 的情况并不少见。重新实现 nrand,使其适用于所有 n 值。
如果n > RAN_MAX我的想法要采取
double temp = n/RAN_MAX + .5;
int mult = temp;
int randomNum = 0;
for (int i = 0; i != mult; mult++)
randomNum += rand();
Run Code Online (Sandbox Code Playgroud)
然后测试是否randomNum < n。这可以生成随机数> RAND_MAX吗?我不知道如何使用比我的计算机可以处理的更大的整数,所以我认为没有任何真正的方法可以分辨。
如果你真的在处理大于你的计算机可以处理的整数,那就很复杂了。
但是对于大于 的整数,您确实有多种选择int,其中包括:unsigned int、long、unsigned long、long long、unsigned long long按大小递增的顺序。具体数字有多大取决于您的架构。
例如,在我的机器上有以下内容:
Data Type: Bytes Minimum Maximum
Short SInt: 2 -32768 32767
Short UInt: 2 0 65535
UInt: 4 0 4294967295
SInt: 4 -2147483648 2147483647
ULong: 8 0 18446744073709551615
SLong: 8 -9223372036854775808 9223372036854775807
ULong Long: 8 0 18446744073709551615
SLong Long: 8 -9223372036854775808 9223372036854775807
Run Code Online (Sandbox Code Playgroud)
因此,如您所见,您可以使数字远大于int32767。
一种方法如下:
double a=rand()/(double)RAND_MAX;
unsigned long long random_n=(unsigned long long)(BIG_MAXIMUM_NUMBER*a);
Run Code Online (Sandbox Code Playgroud)
但是,由于浮点数的离散性质,这可能意味着某些值永远不会出现在输出流中。
C++11 有一个库可以解决这个问题和你提到的问题。其用法的一个例子是:
const int min = 100000;
const int max = 1000000;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(min,max);
int random_int = distribution(generator);
Run Code Online (Sandbox Code Playgroud)
只需更改数据类型即可满足您的大需求。
另一种看待这个问题的方法是,我们可以将其解释rand()为返回一个位字段,并且由于它是统一的 PRNG,因此所有位字段的可能性相同。然后,我们可以多次调用来rand()获取多个同样可能的位字段,并将它们合并以产生大数字。以下是我们如何从两个 8 位随机数生成 16 位随机数:
uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 random_int=b<<8 | a;
Run Code Online (Sandbox Code Playgroud)
只保留返回的rand()&255数字的 8 个最低有效位rand();也就是说,它只保留 的最后一个字节rand()。
将此(uint16)字节转换为无符号 16 位数字。
a<<8将 8 位的位a向左移动,从而为安全添加 留出空间b。
但是,如果rand()返回一个有符号值,使得最高有效位始终为 0 或 1,该怎么办?然后我们可以执行以下操作:
uint16 a=(uint16)(rand()&255);
uint16 b=(uint16)(rand()&255);
uint16 c=(uint16)(rand()&1);
uint16 random_int=c<<14 | b<<7 | a;
Run Code Online (Sandbox Code Playgroud)
我们仅左移b7 位,以便第 8 个最低有效位是随机的。这意味着第 14 个和第 15 个最低有效位将是非随机的。由于我们想要模仿 的行为rand(),因此我们将第 15 个最低有效位保留为非随机的,并抓取一个随机位以左移到第 14 个 LSB 的位置。