亂數有些議題特別拉出來再次討論,不熟的話 可看這篇。
1. [low, up]
假定產生 [10,20] 之整數亂數,先考慮以下程式碼
int( (double)(up-low)*rand()/RAND_MAX+low);
rand() 範圍為 0~RAND_MAX,要產生 up 之情況只有一種:rand() 必須等於 RAND_MAX,無疑不是個均勻之亂數。
------
考慮使用四捨五入之方式
int( (double)(up-low)*rand()/RAND_MAX+low+0.5);
若 (double)(up-low)*rand()/RAND_MAX+low
計算結果為 [10.0,10.5) --> 10
計算結果為 [10.5, 11.5) -->11
...
計算結果為 [19.5, 20) ---> 20
頭尾都不平均。
--------
目前我採用的,欲產生 [low, up] 整數亂數,實際上是產生 [low, up+1) 之整數亂數
int( (double)(up-low+1)*rand()/(RAND_MAX+1)+low);
算式是複雜了點,但認為這麼寫或許可得到「較佳」之效果。
--------
2. 不重覆亂數
Kunth shuffle 大致如下
void KunthShuffle(int *array, int n)
{
for(int i=0; i!=n; ++i) array[i] = i;
for(int i=n-1; i>0; --i){
j=rand_between(0, i); /* j = [0,i] */
swap(array[i], array[j]);
}
}
認為有些場合用不到。如 GA 在隨機挑選二支不同染色體時,直接暴力做即可。
c1 = rand_between(0, population_cnt-1);
do{ c2 = rand_between(0, population_cnt-1); }while(c1==c2);
在一些場合下,或許用亂數跟著排序就好
void SortShuffle(int *array, int n)
{
int *rnd = new int[n];
for(int i=0; i!=n; ++i) array[i] = i;
for(int i=0; i!=n; ++i) rnd[i] = rand(); /* 可和上個 loop 併一起 */
Sort(array, rnd, n); /* 以 rnd 當 key, 交配時 rnd/array 一起換 */
delete [] rnd;
}
--------
建議,Visual Studio 系列,先安裝 SP1 (非英文版 IDE) 或 Feture Pack (英文版 IDE) 回來玩玩,
tr1 裡面有很多寫好的東西,不需再造輪子 (是否有 bug 倒是待測 ),像是 #include <random>,
可先玩玩 tr1::mt19937,為 mersenne twister 之改良。
留言列表