2014-01-28 92 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