2014-01-28 49 views
2

问题的7-9安德鲁·柯尼希加速C++问:获得随机数大于RAND_MAX

7-9。 (困难)对于大于RAND_MAX的参数,§7.4.4/ 135中的nrand的执行不会产生 。通常,这个限制是 没问题,因为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(); 

然后进行测试,看是否randomNum <ñ。这将工作产生一个随机数> RAND_MAX?我不知道如何使用大于我的电脑可以处理的整数,所以我不认为有任何真正的方法可以告诉。

+5

假设您掷出两个骰子并添加结果。与7一样有12个可能吗? –

+0

没错。感谢那 – zzz2991

+0

任何想法解决这个问题的方法? – zzz2991

回答

2

如果你确实用整数大于你的计算机可以处理的整数,那很复杂。

但你必须比int大整数几个选项,其中包括:unsigned intlongunsigned longlong longunsigned 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 

所以,你可以看到,你可以做出比int大得多,要做到这一点是32767

一个路数如下:

double a=rand()/(double)RAND_MAX; 
unsigned long long random_n=(unsigned long long)(BIG_MAXIMUM_NUMBER*a); 

但是,由于浮点数的离散性,这可能意味着某些值将永远不会显示在您的输出流中。

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); 

只需更改数据类型以满足您的大量需求。

另一种看待这个问题的方法是,我们可以将rand()解释为返回一个位字段,并且由于它是一个统一的PRNG,因此所有的位字段具有相同的可能性。然后,我们可以多次调用rand()以获得多个相同可能的位字段并将它们合并为大数字。下面是我们如何将两个8位随机数这样做是为了一个16位的随机数:

uint16 a=(uint16)(rand()&255); 
uint16 b=(uint16)(rand()&255); 
uint16 random_int=b<<8 | a; 

rand()&255只保留8的任何数字rand()回报至少显著位;也就是说,它只保留rand()的最后一个字节。

(uint16)将此字节转换为无符号的16位数字。

a<<8a的8位向左移位,这为安全地添加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; 

我们左移b只有7位,这样第八至少显著位是随机的。这意味着第14和第15个最低有效位将是非随机的。由于我们想要模仿rand()的行为,所以我们将第15个最低有效位保持为非随机,并且抓住一个随机位左移到第14个LSB的位置。

+2

当你从'https://stackoverflow.com/questions/13503671/random-number-bigger-than-100-000/13503714中复制上面的使用'uniform_int_distribution'时#13503714你放弃了播种发电机的注意事项。这可能很重要。 –

+1

@BenjaminBannier,说明仅仅是发电机应该适当播种。应该像cstdlib的'rand()'一样。讨论这可能与此处的兴趣点不同。 – Richard