java 板


LINE

上次那個問題的物件導向版。 支援大數(long)運算。 實做執行期修改權值。updateWeight()方法。 有興趣的大大們玩玩吧。 ____________________________<<程式碼>>____________________________________ package dice; import java.util.Random; import java.util.TreeMap; /** * * @author IANTSAI <br> * 系統:int 32 bits, long 64 bits <br> * 多緒:這不是一個thread safe的物件,請小心。<br> * 用途:一個可以作弊的骰子。<br> * 修改.移植:可以的話,把weightArr、AWArr也換成不定型態,在其他語言,例如C++ 、C#中可以考慮<br> * 修改.移植.實做:weight、AccumulateWeight必須實做 operator(+,+=,-,-=,>,<) * 修改.移植.建議:weight extends int ,AccumulateWeight extends long * @param <T> */ public class WeightRandom<T> { /** * * @param args */ public static void main(String[] args) { String[] valueArr = new String[]{"1點","2點","3點","4點","5點","6點"}; int[] weightArr = new int[]{100,100,100,100,100,10000}; WeightRandom<String> cheatDice = new WeightRandom<String>(); cheatDice.init(valueArr,weightArr); doTest(cheatDice); cheatDice.updateWeight(5,100); doTest(cheatDice); } public static void doTest(WeightRandom<String> cheatDice) { int loop = 1000000; TreeMap<String,Integer> map = new TreeMap<String,Integer>(); long start = System.currentTimeMillis(); for(int i=0;i<loop;i++) { String diceValue = cheatDice.randValue(); if(map.containsKey(diceValue)) map.put(diceValue,map.get(diceValue)+1); else map.put(diceValue,1); } long end = System.currentTimeMillis(); for(String ent : map.keySet()) System.out.println(ent+" : "+map.get(ent)+" 次"); System.out.println(); System.out.println("總共骰了 "+loop+" 次"); System.out.println("花費時間: "+(float)(end-start)/1000+" 秒."); } private T[] valueArr; private int[] weightArr; private long[] AWArr; /** * 初始化 值陣(valueArr) 與 權陣(weightArr) * @param _valueArr 值陣 不可為null, 必須與weightArr等長 * @param _weightArr 權陣 不可為null, 必須與valueArr等長, 元素不可為負數 , * 所有元素的總和不可 == 0 */ public void init(T[]_valueArr,int[]_weightArr) { if(_valueArr==null||_weightArr==null|| _valueArr.length!=_weightArr.length) throw new IllegalArgumentException("different arg length!!!"); this.valueArr = _valueArr; this.weightArr = _weightArr; this.AWArr = createAccumulateWeightArray(_weightArr); } /** * 更新累進權陣 * @return */ public long[] createAccumulateWeightArray(int[] _weightArr) { int size = _weightArr.length; long[] _AWArr = new long[size]; long temp=0; for(int i=0;i<size;i++) { if(_weightArr[i] < 0) throw new IllegalArgumentException("Weight can not < 0!!!"); temp+=_weightArr[i]; _AWArr[i]=temp; } if(temp == 0) throw new IllegalArgumentException("weight Sigma is ZERO!!!"); return _AWArr; } /** * 執行期更新權重矩陣參數,連帶更新AWArr * @param index * @param value */ public void updateWeight(int index, int value) { if(index < weightArr.length) { int def = value - this.weightArr[index]; this.weightArr[index] = value; for(int i=index,j=AWArr.length;i<j;i++) AWArr[i] += def; } else throw new IndexOutOfBoundsException("index="+index); } /** * 依據權重,亂數回傳一個valueArr裡的元素。 * @return */ public T randValue() { //java api 裡沒找到(我懶),所以自己做 long dice = RandUtil.nextLong(AWArr[AWArr.length-1])+1; //自己作來玩的。 int index = LeftAreaFinder.bineryLeftAreaSearch( dice,this.AWArr); return valueArr[index]; } }//end of class /** * * @author IANTSAI *判斷是否落在左區域範圍(右極限)內,如果Key大於最後一個右極限,回傳 -arr.length */ class LeftAreaFinder { private LeftAreaFinder(){} /** * 使用BinarySearch尋找是否落在左區域範圍(右極限)內<br> * ,如果Key大於最後一個右極限,回傳 -arr.length * @param key * @return */ public static int bineryLeftAreaSearch(long key,long[]arr) { int low_of = 0; int up_of = arr.length-1; if(key>arr[up_of])return -arr.length; while (low_of <= up_of) { int middle = (low_of + up_of) >> 1; long midLeft = arr[middle]; if(key < midLeft) up_of = middle-1; else if(key > midLeft)low_of = middle+1; else return middle; } return low_of; } /** * 使用sequenceSearch判斷是否落在左區域範圍(右極限)內,<br> * 如果Key大於最後一個右極限,回傳 -arr.length * @param key * @return */ public static int sequenceLeftAreaSearch(long key,long[]arr) { for(int i=0,j=arr.length;i<j;i++)if(key < arr[i])return i; return -arr.length; } }//end of class /** * 實做長整數的nexLong方法 * @author IANTSAI * */ class RandUtil { private static final int INT32_MAX = 1 << 30;//int 的32位元系統極值 private RandUtil(){} /** * 亂數產生一個在(0~max-1)之間的long 值。 * @param max * @return */ public static long nextLong(long max) { Random rand = new Random(); long randValue; if(max < INT32_MAX)randValue = rand.nextInt((int)max); else randValue = Math.abs(rand.nextLong()) % max; return randValue; } } ________________________________<<程式碼結束>>_______________________________ -- --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 60.248.27.110 ※ 編輯: zanyking 來自: 60.248.27.110 (04/10 13:46)







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:WOW站內搜尋

TOP