※ 引述《oniki.bbs@ptt.cc (宇治金時月見雪)》之銘言:
> 有10%的機率出現18~20
> 有30%的機率出現11~17
> 剩下的60%機率出現0~10
> 請問該怎麼做呢 謝謝各位
需X個數字
其中10%的Outcome A={18,19,20}
其中30%的Outcome B={11,12,13..17}
其中60%的Outcome C={0,1,2,.10}
由A中, 抽 X*0.1 次
由B中, 抽 X*0.3 次
由C中, 抽 X*0.6 次
再亂序放入martix
ps. 不滿一次的自己補上XD
--
※ Origin: SayYA 資訊站 <bbs.sayya.org>
◆ From: 163.26.34.214
◆ Modify: 06/03/09 11:27:09 <163.26.34.214>
> -------------------------------------------------------------------------- <
作者: ogamenewbie (觸摸著銀河的新手) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Thu Mar 9 12:54:28 2006
我現在在用的是...
先設好一個檔案,
裡面格式是 name min max freq [freq ...]
例如說我今天說 aaa 1 3 9 5 1
這在程式裡面代表的意思就是
aaa 這個東西如果出現 15 次(9+5+1, freq總和)
其中有 9 次(第1個freq)會是 1 (min, 迴圈起始條件),
5 次(第2個freq)會是 2,
1 次(第3個freq)會是 3 (max, 迴圈終止條件)
去檔案抓值出來放...
開一個陣列, 長度是freq總和
照每一個元素的出現次數放進陣列裡面...
然後照機率跟名字依序放進陣列
例如 A[0] = 1;
A[1] = 1;
A[2] = 1;
...
A[8] = 1;
A[9] = 2;
A[10] = 2;
...
A[13] = 2;
A[14] = 3;
依此類推 (實際程式碼當然是用迴圈去放, 這邊是為了解說...)
然後再去那個陣列隨機從中抓值就好了...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 163.25.148.49
> -------------------------------------------------------------------------- <
作者: PsMonkey (痞子軍團團長) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Thu Mar 9 13:55:10 2006
當然是包物件阿... 寫 Java 怎麼可以不包物件... \囧/
(路人:這... 不相關吧? ==.==)
我的做法跟上面幾位大大不一樣...
首先,要有幾個 Utility,裡頭有一些 method 長得像這樣
public static double[] aDistributeMethod(int amount){
double[] result = new double[amount];
for(int i=0; i<amount; i++){
result[i]=aProbProduct();
}
return result;
}
/*
* 假設 distribution 為 {1, 2, 1}
* 則 value 傳入 0~1 時候回傳 0,傳入 1.x~3 時回傳 1,3.x~ 回傳 2
*/
public static int valueLocationAt(double[] distribution, double value){
double sum = 0;
for(int i=0; i<distribution.length; i++){
sum+=distribution[i];
if(value<=sum){
return i;
}
}
return distribution.length;
}
aProbProduct() 就看你要怎麼弄
要 poisson 還是什麼鬼的,請隨意
寫一個我喜歡用 Seed 作結尾的物件,這裡就叫做 FooSeed 吧
public class FooSeed {
private final String pool[];
private double distribution[];
private double totalProbability;
public FooSeed(int totalAmount){
pool = new String[totalAmount];
distribution = Distribution.poisson(totalAmount);
for(int i=0; i<pool.length; i++){
pool[i] = "\\囧/";
}
totalProbability = Calculate.sumOfArray(distribution);
}
public double getTotalProbability(){
return totalProbability;
}
public String pickFoo(){
double value = Distribution.random(0.0, totalProbability);
int index = Distribution.valueLocationAt(distribution, value);
return pool[index];
}
}
那麼,只要 new FooSeed
然後對 FooSeed 一直 pickFoo 就好
這是我的做法,還請各方高手多多指點 [擺茶點]
=====
最近在寫的案子... T__T
====
ㄟ對,qrttOne,再來篇比較的文章吧
我好想 m 阿.... \囧/
--
侃侃長論鮮窒礙 網站:http://www.psmonkey.idv.tw
眾目睽睽無心顫 個人版:telnet://legend.twbbs.org
煢居少聊常人事
殺頭容易告白難 歡迎參觀 Java 版(@ptt.cc)精華區 \囧/
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 203.204.16.17
> -------------------------------------------------------------------------- <
作者: TonyQ (骨頭) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Thu Mar 9 15:34:40 2006
※ 引述《oniki (宇治金時月見雪)》之銘言:
: 這是我的程式碼
: Random ra = new Random();
: int[][] M = new int[10][10];
: for (int i=0;i<10;i++){
: for(int j=0;j<10;j++){
: M[i][j]=ra.nextInt(21);
: }
: }
: 這樣是在會產生一個10x10的矩陣
: 裡面的element都是0~20的亂數
: 我想問的是
: 要怎樣才能夠讓每個element的值有機率性的落在0~20中的某些特定範圍
: 舉例說
: 我想要讓這個element
: 有10%的機率出現18~20
: 有30%的機率出現11~17
: 剩下的60%機率出現0~10
: 請問該怎麼做呢 謝謝各位
好久沒看到這麼好玩的問題了!!
讓人忍不住手癢實作了一個XD (程式碼很醜 請諸位大德鞭小力一點 orz)
我的作法是把機率量化
比方說10 30 60 (如果有小數點就四捨五入)
然後亂數產生0~100的數字 看它落在哪個區間
就去產生那個區間的亂數 比方說落在 0~10好了 就產生18~20之間的亂數
不過我習慣用Math.random() 跟原po不一樣就是了XD
底下有實作的程式碼
node是我用來代表區間的參數
constructer 第一個放start 第二個是end 第三個是機率
比方說 有10%的機率出現18~20 就是 (18,20,10)
<---> %
--
這裡順便附上我測試用的程式碼
RandomNum rn=new RandomNum();
rn.addMoreNode(18,20,10);
rn.addMoreNode(11,17,30);
rn.addMoreNode(0,10,60);
int[] ary=new int[21];
for(int i=0;i<10000;i++) ary[rn.getRandomNum()]++;
int sum1=0;
for(int i=0;i<=10;i++) sum1+=ary[i];
int sum2=0;
for(int i=11;i<=17;i++) sum2+=ary[i];
int sum3=0;
for(int i=18;i<=20;i++) sum3+=ary[i];
System.out.println("區間1:"+sum1/10000.0);
System.out.println("區間2:"+sum2/10000.0);
System.out.println("區間3:"+sum3/10000.0);
--
class RandomNum{
int count;
LinkedList<node> nodeList;
RandomNum(){
nodeList=new LinkedList<node>();
count=0;
}
boolean addMoreNode(node in){
count+= (int)(in.chance +0.5);
return nodeList.add(in);
}
boolean addMoreNode(int start ,int end,double chance){
node in=new node(start,end,chance);
count+= (int)(in.chance +0.5);
return nodeList.add(in);
}
int getRandomNum(){
int k=(int)(Math.random()*count)+1;
int index=0;
while(index<size()&&k>0){
node temp= nodeList.get(index);
k-= (int)(temp.chance +0.5);
index++;
}
index--;
return nodeList.get(index).getNum();
}
int size(){
return nodeList.size();
}
}
class node{ //用來代表所需要的節點
double chance;
int start;
int end;
int size;
node(int start1 ,int end1,double chance1){
start = start1;
end = end1;
chance = chance1;
size = end-start+1;
}
int getNum(){
return (int)(Math.random()*(end-start+1)) + start;
}
}
--
String temp="relax"; | Life just like programing
while(buringlife) String.forgot(temp); | to be right or wrong
while(sleeping) brain.setMemoryOut(); | need not to say
stack.push(life.running); | the complier will
stack.push(scouting.buck()); | answer your life
stack.push(bowling.pratice()); | Bone everything
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.138.240.58
※ 編輯: TonyQ 來自: 140.138.240.58 (03/09 15:36)
> -------------------------------------------------------------------------- <
作者: zanyking (遙遠的旅人) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Sun Mar 12 04:38:56 2006
之前好像有看過類似的問題...可以參考一下。
文章網址如下:
http://www.javaworld.com.tw/jute/post/view?bid=29&id=141413&sty=1
如果眼睛不嫌累的話,就看以下的程式碼吧。
_________________________________________________________________
package test;
public class DiscreteProcessor
{
protected int X1;
protected int X2;
protected int[] arr;
/**
* 設定曲線方程式跟區間(x1,x2)
* @param fomula
* @param X1
* @param X2
*/
public void init(CurveFomula fomula,int X1,int X2)
{
this.X1 = X1;
this.X2 = X2;
arr = new int[X2-X1];
for (int i = 0, j = arr.length; i < j; i++)
{
int X = X1 + i;// 現在的X值
arr[i] = fomula.excute(X);
// System.out.println("arr[" +i+ "]" + arr[i]);
}
}
/**
* 從X1開始,到X2結束,求算曲線積分值,
* @return
*/
public long sigmaDiscrete()
{
long SUM = 0;
for (int i = 0, j = arr.length; i < j; i++)
SUM += arr[i];
return SUM;
}
/**
* 取得符合該Fomula的整數離散數列,從X1開始,到X2結束
* @return
*/
public int[] getDiscreteSamples()
{
return arr;
}
/**
* @param args
*/
public static void main(String[] args)
{
int x1 = 1;
int x2 = 1001;
int length = x2-x1;
Ah_taiCurveFomula fomula1 = new Ah_taiCurveFomula();
DiscreteProcessor processor = new DiscreteProcessor();
processor.init(fomula1,x1,x2);
int[] testData = new int[length];//測試統計結果
for (int i = 0, j = 1000000; i < j; i++)
{
int pickData = diceValue(processor.sigmaDiscrete(),
processor.getDiscreteSamples());//多骰幾次,統計一下
testData[pickData]++;
}
for (int i = 0, j = length; i < j; i++)
{// 試看看列印出來答案跟權陣的比例一不一樣?
// System.out.println("ans[" + i + "]" + testData[i]);
System.out.println(testData[i]);
}
}
/**
* Random出來一個參數,然後看他落在哪個權陣區間...燈燈燈,答案出來瞭
*
* @param q
* @param weightArr
* @return
*/
public static int diceValue(long SUM, int[] weightArr)
{
double total = Math.random() * SUM;
int temp = 0;
for (int i = 0, j = weightArr.length; i < j; i++)
{
temp += weightArr[i];
if (total <= temp)
{
return i;
}
}
return -1;// an fatal Error!!!
}
}
interface CurveFomula
{
/**
* Y = f(x),輸入X,求Y,直接叫f of x太難聽.
* @param X
* @return f(X)
*/
int excute(int X);
}
/**
* @author Ian
*一個CurveFomula的實作,你也可以實作自己的
*/
class MyCurveFomula implements CurveFomula
{
public int excute(int X)
{
return (int) Math.floor(700000 / X);
}
}
/**
*
* @author Ian
*一個CurveFomula的實作,用你給的方程式
*/
class Ah_taiCurveFomula implements CurveFomula
{
/**
* y=1/400 * e ^ ((-1/400)*x)
*
*/
public int excute(int X)
{
return (int) Math.floor(Math.pow(Math.E,((-1d/400d)*X))*100000d/400d) ;
}
}
___________________________________________________________________________
原理是這樣的:
你先開一個地址存放陣列addressArr:
int[] addressArr = new int[]{1,2,3};
然後開一個權重存放矩陣weightArr:
int[] weightArr = new int[]{9,5,1};
再來,亂數產生器產生從 [min ~ SUM(min~max)]
中的任一亂數X。
int address = -1;
int sum = 0;
for(int i=0;i<weightArr.length;i++)
{
sum += weightArr[i];
if(X<sum)
{
address = i;
break;
}
}
這時候,addressArr[X]就是你要的答案。
雖然JAVA沒有指標,你還是可以開陣列去模擬這樣的概念。
隨機產生出來的大量亂數在統計上就會服從你給的曲線分佈。
不曉得能不能解決問題?
PS:to 版主,kkcity跟這裏好像已經Async了...
--
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 210.85.116.116
> -------------------------------------------------------------------------- <
作者: AI3767 (AI3767) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Tue Mar 14 22:17:55 2006
不好意思, 這個主題已經很久了
想說試著寫一個一般型的來試看看
下面有主要程式的程式碼, 寫的不好請見諒
作法很直觀, 就是看機率落在那個範圍
再從那個範圍內取亂數
主要由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);
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%.
* <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()
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()
} //{END class} class RangeRandom
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.123.105.166
※ 編輯: AI3767 來自: 140.123.105.166 (03/14 22:21)
> -------------------------------------------------------------------------- <
作者: zanyking (遙遠的旅人) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Tue Mar 14 23:57:53 2006
※ 引述《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
> -------------------------------------------------------------------------- <
作者: AI3767 (AI3767) 看板: java
標題: Re: [問題] 亂數產生一個矩陣
時間: Wed Mar 15 01:52:20 2006
※ 引述《zanyking (遙遠的旅人)》之銘言:
: : private RangeRandom(int[] rangeArr, int off, float[] probArr) {
: : offset = off;
: : probabilityArray = probArr;
: : setAccumulateArray(rangeArr);
: : setProbArray(probArr);
: 這裡的寫法很可怕,難懂,又容易錯。
: 兩個set方法互相要求對方的成員跟自己的長度要一樣,而且你是先讓:
: probabilityArray = probArr;來方便你取得正確的長度
: 可是在setProbArray(probArr);卻又一定會把probArr指向另外一個值。
: 這樣寫很危險。
嗯...這裡其實, 在setProbArray的方法裡, 並不會將probArr指向另一個值
因為實作上, 是將probArr做了累積計算放到probabilityArray裡
為的是在取亂數時較為簡易快速
雖然在建構時做了assign的動作, 但在setProbArray裡,
會重新assign新的陣列, 這樣不會改動到原 probArr
而且在物件建出後, 還可以重新設定新的機率, 但是得和原範圍數量相等
例如 probArr為{0.2f,0.7f,0.1f}則在setProbArray裡
會將probabilityArray={0.2f, 0.9f, 1.0f}
本來是想將 set 的方法都private掉, 避免誤用
但想說至少 protected 的話, 還有機會被override掉, 如果不滿意的話 ^^
: : 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};
若是直接給定的話, 的確是難用的, 我的設想是在
使用者應該會去維護一個範圍array,如rArr,以及對映的機率array,如pArr
然後在要用時, 才去createRangeRandom(rArr,0,pArr)
而上面您給的例子, 可以是
int[] rangs = {4, 1, 1};
float probs = {0.4f, 0.2f, 0.3}; //其實會exception, 因為總和不為1.0f
createRangeRandom(rangs, 2, probs);
真正的缺點是在於如果要用的範圍中間是有大量小範圍gap時,
例如: 要 1~20, 22~25, 27~30, 31~35, 37~38 40~42
: 這樣的使用者介面超難用。
: 因為事實上,我並不需要知道個別值佔總體的比例,我只需要知道一個純量的權重就好。
: 也就是說像這樣:
: new int[]{12,123,34,1,6,77}
: 至於個別比例是多少,是寫程式的人要負責算的。
: : * <p>
: : * <code>probs<code> 機率陣列的機率和, 必須為 1.0f, 否則會丟出一個
: : * <code>RuntimeException</code>
...
: : 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); 就好了。
: 寫程式,好懂的一行文才是王道。^^
這邊是不能用這樣的作法, 原因就在於我用的probabilityArray
實際是原機率array的累計值, 而每個範圍的機率不同,
所以取亂數時, 會依照random出來的float值,
來找出所對映的所在範圍
以上面的例子, 機率為 0.2f 0.7f 0.1f
所以probabilityArray為 0.2f 0.9f 1.0f
當取float時, 若是 0.0~0.2 , 則會再從第1個範圍去取亂數,
這才是真正會回傳的亂數
若 float值>0.2 且<=0.9f, 則在第2個範圍取亂數
同樣當值>0.9f且 <=1.0f, 則在第3個範圍取亂數
而使用Arrays.binaraySearch在於當找不到時,
回傳的值是 -(insertion point)-1, 這個在Documentation內有解釋
: : 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()
...
: 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: 140.123.219.115
※ 編輯: AI3767 來自: 140.123.219.115 (03/15 01:54)
※ 編輯: AI3767 來自: 140.123.219.115 (03/15 01:59)
※ 編輯: AI3767 來自: 140.123.219.115 (03/15 02:01)