今天同學出了這樣一個題,讓我們大家來討論,大家都提出了很多方法,最後在CSDN上搜了一個相關的文章,感覺上面寫的演算法挺雜的,想看原帖的如下
其實有一個非常令人信服的演算法,實現也比較也比較簡單。就是利用我們學電腦的基礎--進位(2進位,8進位等)思想來完成的。
前提有一個普適的規律:1、任何一個進位類型都可以表示任意一個數字。
2、進位的每一位上的數,出現的值範圍都是一樣的,如2進位,每位中只能出現0,1;8進位,每位中只能出現0~7;7進位,每位上出現0~6中的數是機率都是相等的。
基於以上的2個規律,得到了以下兩種較準確的演算法。
1.取0~39內的數除於4取整,得到範圍為0~9(每個取值的數都是機會均等的)
代碼如下:
int rand10(){ int i; int j; int Tworesult;//表示的兩位7進位,其十進位的範圍是0~48 do { i = rand7() - 1; j = rand7() - 1; Tworesult = i * 7 + j; } while(Tworesult >= 40); return Tworesult/4 + 1;}
模擬100w次的結果如下:
1次數:99938
2次數:99523
3次數:100191
4次數:99723
5次數:100169
6次數:99864
7次數:100732
8次數:99854
9次數:100134
10次數:99872
如果將上面程式的最後一句改為 Tworesult %10 + 1;
100w次的模擬結果如下:
1次數:100075
2次數:100447
3次數:99600
4次數:99535
5次數:100685
6次數:99633
7次數:100121
8次數:99920
9次數:100034
10次數:99950
兩者的結果其實是一樣的
2.取40~49的數模數10(mod(10)),得到範圍的0~9(每個取值的數都是機會均等的)
int rand10(){ int i; int j; int Tworesult;//表示的兩位7進位,其十進位的範圍是0~48 do { i = rand7() - 1; j = rand7() ; Tworesult = i * 7 + j; } while(Tworesult < 40); return Tworesult%10 + 1;}
100w的模擬結果如下:
1次數:100171
2次數:100506
3次數:99827
4次數:99713
5次數:99875
6次數:99979
7次數:100454
8次數:100043
9次數:99675
10次數:99757
總結:
這兩種方法都達到了題目要求的效果,但是對於大量資料統計而言,演算法1的時間效率明顯要高於演算法2。