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