我處於編碼環境中,我只能訪問一些最基本的c函數。 #include'其他lib不可行。如何從c函數中獲取較大的隨機數rand()
在這個環境中,我可以調用rand(),它給我一個隨機數,介於0到32767之間,包含在我的環境中(我認爲)。下面的代碼是正確的邏輯來獲得一個較大的隨機數,它是均勻分佈的,如/ rand()?
rnum = rand() * (32767 + 1) + rand();
我處於編碼環境中,我只能訪問一些最基本的c函數。 #include'其他lib不可行。如何從c函數中獲取較大的隨機數rand()
在這個環境中,我可以調用rand(),它給我一個隨機數,介於0到32767之間,包含在我的環境中(我認爲)。下面的代碼是正確的邏輯來獲得一個較大的隨機數,它是均勻分佈的,如/ rand()?
rnum = rand() * (32767 + 1) + rand();
rnum = (rand() << 15) | rand()
可能會更快,但如果你需要高質量的隨機數字,你應該尋找一個外部庫。內置的隨機函數通常只適用於最簡單的應用程序。
如果你曾經移植過RAND_MAX是一個非常有價值的平臺,那麼我會用'^'來代替'|',以避免問題。 – Cairnarvon 2013-04-26 23:33:05
我會繼續推薦[Mersenne Twister](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html)。我自己的[OneJoker](http://github.com/lcrocker/onejoker)庫也有一個很好的發生器。 – 2013-04-27 00:09:57
沒有理由認爲這會比OP的解決方案更快,事實上你的解決方案是錯誤的,因爲<< 16被定義爲乘以65536,而不是32768. – 2013-04-27 01:17:06
在使用ANY隨機數發生器進行非平凡使用之前,應該對其進行廣泛的測試。 Here是關於此主題的一篇文章的鏈接。
在二戰時期布萊切利公園的破譯者的各種歷史中,都可以找到關於甚至是真隨機數弱點的有趣背景。德國人和希特勒在戰爭的大部分時間都假定他們的密碼因爲被隨機數字加密而不可破解,而英國人在幾個月內完全破解了所有這些密碼,因爲德國實施「隨機性」的各種弱點。許多代碼在幾天或幾個月內被充分「扭曲」,即使沒有被完全破壞,也足以被使用。
static unsigned long next = 1;
int my_rand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % (RAND_MAX+1));
}
void my_srand(unsigned int seed) {
next = seed;
}
在Linux上
#define RAND_MAX 2147483647
環境RAND_MAX大概是32767
參考:http://en.wikipedia.org/wiki/Linear_congruential_generator
如果你沒有內存限制,你也可以看看http://en.wikipedia.org/wiki/Mersenne_twister代碼嵌入作爲就像上面的例子一樣
除了這裏提出的其他優秀解決方案之外,您還可以在RAND_MAX中進行功率擴展,在用戶定義的MY_RAND_MAX處截斷,並丟棄將導致均勻性被破壞的解決方案。
int myrand(int MY_RAND_MAX)
{
int j = 0, num = 0;
// Generate digits for expansion in powers of RAND_MAX, up to acceptable range.
while (pow(RAND_MAX + 1, j) <= MY_RAND_MAX){
num = num + rand() * (int)pow(RAND_MAX + 1, j);
j++;
}
//compute remainder to determine truncation
int remainder = ((int)pow(RAND_MAX + 1, j)) % (MY_RAND_MAX + 1);
// If number is within accepted bounds, mod and return
if (num <= ( (int)pow(RAND_MAX + 1, j) - remainder)){
return (num % (MY_RAND_MAX + 1));
// Else, if number generated exceeds allowed bounds, rerun method.
}else if (num > ( (int)pow(RAND_MAX + 1, j) - remainder)){
return myrand(MY_RAND_MAX);
}else{
exit(-1);
}
}
可以憑經驗檢查這種方法讓你在給定範圍內的統計均勻的輸出。
我已經完成了幾次不同範圍的試驗,每個試驗的樣本量都是100000,並且樣本的方差和預期的方差至少達到了3個sig。每次都是圖。
p.s.我不是一名編碼員,而是一位最近學會編碼的數學家/物理學家,所以我對代碼質量的任何和所有反饋將不勝感激。
由於均勻分佈蘭特是..確實高榮譽。你真的不能包含三十行BSD授權代碼,並且包含arc4random或其他東西來正確地完成這項工作,或者讀出/ dev/random? – 2013-04-26 23:23:07
你應該說你的環境是什麼,但它聽起來很垃圾。請告訴我們您沒有任何強烈的需求,這些數字是無法猜測的! – 2013-04-26 23:25:13
許多嵌入式環境在可立即使用的庫中受到限制。 – Marvo 2013-04-26 23:29:26