Re: [問題] 亂數產生一個矩陣
※ 引述《AI3767 (AI3767)》之銘言:
: 不好意思, 這個主題已經很久了
: 想說試著寫一個一般型的來試看看
: 下面有主要程式的程式碼, 寫的不好請見諒
: 作法很直觀, 就是看機率落在那個範圍
: 再從那個範圍內取亂數
: 主要由Factory method取得一個物件
: 然後這個物件就可以用getRand()來取值了
: package tw.edu.ccu.cs.ailab;
: import java.util.Arrays;
: import java.util.Random;
: public class RangeRandom {
:   private Random genRandom;
:   private int[] accumulateArray;
:   private int offset;
:   private float[] probabilityArray;
:   private RangeRandom(int[] rangeArr, int off, float[] probArr) {
:     offset = off;
:     probabilityArray = probArr;
:     setAccumulateArray(rangeArr);
:     setProbArray(probArr);
這裡的寫法很可怕,難懂,又容易錯。
兩個set方法互相要求對方的成員跟自己的長度要一樣,而且你是先讓:
probabilityArray = probArr;來方便你取得正確的長度
可是在setProbArray(probArr);卻又一定會把probArr指向另外一個值。
這樣寫很危險。
:     genRandom = new Random();
:   } //{END constructor}
:   /** 利用 <code>range</code> 陣列所設定的各個範圍大小, 相對同個索引位置的
:    *  <code>probs</code> 陣列是該位置範圍的機率. <p>
:    *  舉例當呼叫 <code>createRangeRandom(new int[]{1,3,2}, 2,
:    *  new float[]{0.2f,0.7f,0.1f})</code>,<br>
:    *  則亂數產生 2 的機率有 20%; 3, 4, 或5 的機率有 70%; 6 或 7 的機率有 10%.
這裡非常的難懂、也非常的不好用。那個new int[]{1,3,2}
指的是從2開始1個數、3個數、2個數吧?
也就是說如果我想要2,3,4,5,6,7分別有不同的機率我就要宣告:
rangs = new int[]{1,1,1,1,1,1};
probs = new float[]{0.1f,0.1f,0.1f,0.1f,0.2f,0.3f};
這樣的使用者介面超難用。
因為事實上,我並不需要知道個別值佔總體的比例,我只需要知道一個純量的權重就好。
也就是說像這樣:
new int[]{12,123,34,1,6,77}
至於個別比例是多少,是寫程式的人要負責算的。
:    *  <p>
:    *  <code>probs<code> 機率陣列的機率和, 必須為 1.0f, 否則會丟出一個
:    *  <code>RuntimeException</code>
:    *  @param range 存放各範圍大小的陣列
:    *  @param offset 表示要產生亂數的起始值
:    *  @param probs 存放各範圍機率的陣列
:    */
:   public static RangeRandom createRangeRandom(int[] range, int offset,
:       float[] probs) {
:     return new RangeRandom(range, offset, probs);
:   } //{END factory} public static RangeRandom createRangeRandom()
:   private int getCase() {
:     int c = Arrays.binarySearch(probabilityArray, genRandom.nextFloat());
:     if( c<0 ) return -(++c);
:     else return c;
:   } //{END} private int getCase()
如果是要練習Arrays.binarySearch...那不錯。
不過事實上:return genRandom.nextInt(probabilityArray.length); 就好了。
寫程式,好懂的一行文才是王道。^^
:   public int getRand() {
:     int caseRange = getCase();
:     if( caseRange==0 )
:       return offset+genRandom.nextInt(accumulateArray[0]-offset);
:     else
:       return accumulateArray[caseRange-1]+genRandom.nextInt(
:           accumulateArray[caseRange]-accumulateArray[caseRange-1]);
:   } //{END} public int getRand()
:   protected void setProbArray(float[] probArr) {
:     if( probArr.length!= accumulateArray.length )
:       throw new RuntimeException("Array size doesn't match.");
:     float test = 0f;
:     probabilityArray = new float[probArr.length];
:     for(int i=0; i<probArr.length; i++) {
:       test += probArr[i];
:       probabilityArray[i] = test;
:     }
:     if( test!= 1.0f )
:       throw new RuntimeException("Probability doesn't equal to 1.0.");
:   } //{END} protected void setProbArray()
:   protected void setAccumulateArray(int[] rangeArr) {
:     if( rangeArr.length!= probabilityArray.length )
:       throw new RuntimeException("Array size doesn't match.");
:     int total = offset;
:     accumulateArray = new int[rangeArr.length];
:     for(int i=0; i<rangeArr.length; i++) {
:       total += rangeArr[i];
:       accumulateArray[i] = total;
:     }
:   } //{END} protected void setRangeArray()
        public static void main(String[] args)
        {
                RangeRandom rand = new RangeRandom(new int[]{1,3,2},2,new
float[]{0.2f,0.7f,0.1f});
                TreeMap<Integer,Integer> ansMap = new TreeMap<Integer,Integer>() ;
                for(int i=0;i<100000;i++)
                {
                        int test = rand.getRand();
                        if(ansMap.containsKey(test)) ansMap.put(test,ansMap.get(test)+1);
                        else ansMap.put(test,1);
                }
                for(Map.Entry<Integer,Integer> ent : ansMap.entrySet())
                {
                        System.out.println("ans["+ent.getKey()+"]="+ent.getValue());
                }
        }
//給你一個main()不然不能測。
: } //{END class} class RangeRandom
其實這個問題,大家原理應該都是大同小異的。
我是給分佈方程式class,產生機率亂數。
也可以給離散數列,設成權陣Array輸入,產生機率亂數。
道理都相同的。
--
--
※ 發信站: 批踢踢實業坊(ptt.cc) 
◆ From: 210.85.116.116
討論串 (同標題文章)
java 近期熱門文章
PTT數位生活區 即時熱門文章