java随机数生成具体实现代码
程序员文章站
2024-03-09 16:00:17
本文实例为大家分享了java随机数生成代码,供大家参考,具体内容如下
package com.gonvan.common.utils;
import ja...
本文实例为大家分享了java随机数生成代码,供大家参考,具体内容如下
package com.gonvan.common.utils; import java.util.*; /** * 随机数工具 * * @author yuerzm * */ public final class lotteryaliasmethod { /** * the random number generator used to sample from the distribution. */ private final random random; /** * the alias tables. */ private final int[] alias; /** * the probability tables. */ private final double[] probability; /** * constructs a new aliasmethod to sample from a discrete distribution and * hand back outcomes based on the probability distribution. * <p/> * given as input a list of probabilities corresponding to outcomes 0, 1, * ..., n - 1, this constructor creates the probability and alias tables * needed to efficiently sample from this distribution. * * @param probabilities * the list of probabilities. */ public lotteryaliasmethod(list<double> probabilities) { this(probabilities, new random()); } /** * constructs a new aliasmethod to sample from a discrete distribution and * hand back outcomes based on the probability distribution. * <p/> * given as input a list of probabilities corresponding to outcomes 0, 1, * ..., n - 1, along with the random number generator that should be used as * the underlying generator, this constructor creates the probability and * alias tables needed to efficiently sample from this distribution. * * @param probabilities * the list of probabilities. * @param random * the random number generator */ public lotteryaliasmethod(list<double> probabilities, random random) { /* begin by doing basic structural checks on the inputs. */ if (probabilities == null || random == null) throw new nullpointerexception(); if (probabilities.size() == 0) throw new illegalargumentexception("probability vector must be nonempty."); /* allocate space for the probability and alias tables. */ probability = new double[probabilities.size()]; alias = new int[probabilities.size()]; /* store the underlying generator. */ this.random = random; /* compute the average probability and cache it for later use. */ final double average = 1.0 / probabilities.size(); /* * make a copy of the probabilities list, since we will be making * changes to it. */ probabilities = new arraylist<double>(probabilities); /* create two stacks to act as worklists as we populate the tables. */ deque<integer> small = new arraydeque<integer>(); deque<integer> large = new arraydeque<integer>(); /* populate the stacks with the input probabilities. */ for (int i = 0; i < probabilities.size(); ++i) { /* * if the probability is below the average probability, then we add * it to the small list; otherwise we add it to the large list. */ if (probabilities.get(i) >= average) large.add(i); else small.add(i); } /* * as a note: in the mathematical specification of the algorithm, we * will always exhaust the small list before the big list. however, * due to floating point inaccuracies, this is not necessarily true. * consequently, this inner loop (which tries to pair small and large * elements) will have to check that both lists aren't empty. */ while (!small.isempty() && !large.isempty()) { /* get the index of the small and the large probabilities. */ int less = small.removelast(); int more = large.removelast(); /* * these probabilities have not yet been scaled up to be such that * 1/n is given weight 1.0. we do this here instead. */ probability[less] = probabilities.get(less) * probabilities.size(); alias[less] = more; /* * decrease the probability of the larger one by the appropriate * amount. */ probabilities.set(more, (probabilities.get(more) + probabilities.get(less)) - average); /* * if the new probability is less than the average, add it into the * small list; otherwise add it to the large list. */ if (probabilities.get(more) >= 1.0 / probabilities.size()) large.add(more); else small.add(more); } /* * at this point, everything is in one list, which means that the * remaining probabilities should all be 1/n. based on this, set them * appropriately. due to numerical issues, we can't be sure which * stack will hold the entries, so we empty both. */ while (!small.isempty()) probability[small.removelast()] = 1.0; while (!large.isempty()) probability[large.removelast()] = 1.0; } /** * samples a value from the underlying distribution. * * @return a random value sampled from the underlying distribution. */ public int next() { /* generate a fair die roll to determine which column to inspect. */ int column = random.nextint(probability.length); /* generate a biased coin toss to determine which option to pick. */ boolean cointoss = random.nextdouble() < probability[column]; /* based on the outcome, return either the column or its alias. */ return cointoss ? column : alias[column]; } }
以上就是本文的全部内容,希望对大家的学习有所帮助。