java生成m到n的随机数
java怎么生成m至n的随机数,java提供2种简便生成随机数的方式。
第一种:是java.lang.Math类的Math.Random(),其实底层也是new Random()后面再介绍;
第二种:是java.util.Random类,Random random = new Random();
函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间。
返回值是一个伪随机选择的数(近似)均匀分布的范围。
实例代码
生成[0-1)的方法,范围0<=r<1,大于等于0且小于1
double r = Math.random(); System.out.println(r);
生成[0,n)的方法,范围0<=r<n,大于等于0且小于n
Random rand = new Random(); int r = rand.nextInt(n); System.out.println(r);
生成[0,n]的方法,范围0<=r<=n,大于等于0且小于等于n
int r = (int)Math.round(Math.random() * n); System.out.println(r);
生成[m,n]的方法,范围m<=r<=n,大于等于m且小于等于n
int r = (int)Math.round(Math.random()*(n-m) + m); System.out.println(r);
解释
Math.Random(),其实底层也是调用Random random = new Random();的,来看看底层源码片段:
/** * 返回一个带正号的{@code double}值,更大 * 大于或等于{@code 0.0},小于{@code 1.0}。 * 返回值的选择(近似)均匀分布的范围。 * * 当这个方法被首次调用时,它会创建一个新的 * 伪数字生成器,就像通过表达式一样 * * {@code新java.util.Random()} * 之后使用这个新的伪数字生成器 * 所有对该方法的调用,并无其他用途。 * * 此方法正确同步,允许正确使用 * 不止一个线程。但是,如果许多线程需要生成 * 伪随机数以较大的速度,可以减少争用 * 每个线程都有自己的伪数字生成器。 * @返回一个大于或等于的伪随机{@code double} * 对{@code 0.0}和小于{@code 1.0}。 * @see随机# nextDouble() */ public static double random() { Random rnd = randomNumberGenerator; if (rnd == null) rnd = initRNG(); return rnd.nextDouble(); }
private static Random randomNumberGenerator; private static synchronized Random initRNG() { Random rnd = randomNumberGenerator; return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd; }
可以看出,当randomNumberGenerator是静态变量,如果为空,测创建一个新的Random赋值给randomNumberGenerator。
再看看Random的构造函数,使用一个seedUniquifier() ^ System.nanoTime()返回值作为种子数。构造唯一标识种子。
/** * 创建一个新的随机数生成器。这个构造函数集 * 随机数产生器的种子极有可能 * 与此构造函数的任何其他调用不同。 */ public Random() { this(seedUniquifier() ^ System.nanoTime()); }
private static long seedUniquifier() { // L'Ecuyer, "Tables of Linear Congruential Generators of // Different Sizes and Good Lattice Structure", 1999 for (;;) { long current = seedUniquifier.get(); long next = current * 181783497276652981L; if (seedUniquifier.compareAndSet(current, next)) return next; } }
什么是种子:使用一个{@code long}种子创建一个新的随机数生成器,种子是伪随机的内部状态的初始值。种子还可以通过setSeed设置:
Random rand = new Random(); long code = 100; rand.setSeed(code);
探究
种子相同情况
Random rand1 = new Random(100); Random rand2 = new Random(100); for(int i=0;i<10;i++) { System.out.print(rand1.nextInt(10)); System.out.print(" "); System.out.print(rand2.nextInt(10)); System.out.println(); }
5 5 0 0 4 4 8 8 1 1 6 6 6 6 8 8 3 3 3 3
种子相同,就算实例也不同,不管运行多少次,打印出的随机数都是相同的。输出相同,如果知道种子值,能猜测下一位随机数。
种子不同情况
Random rand1 = new Random(); Random rand2 = new Random(); for(int i=0;i<10;i++) { System.out.print(rand1.nextInt(10)); System.out.print(" "); System.out.print(rand2.nextInt(10)); System.out.println(); }
5 4 1 6 2 3 3 8 7 6 9 6 1 9 8 9 0 5 0 0
种子不同,不管实例相不相同,都不会生成相同的随机数。
总结
1. 同一个种子,生成N个随机数,当你设定种子的时候,这N个随机数是什么已经确定。相同次数生成的随机数字是完全相同的。(例1)
2. 如果用相同的种子创建两个Random实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。(例1)
3. Java的随机数都是通过算法实现的,Math.random()底层是调用Random()类,实例唯一。
4. 使用java.util.Random()会相对来说比较灵活一些,可以产生正态、高斯、均匀分布的随机数。
应用实例
附带个实例
题目:求10个-100到100的随机数绝对值的最新小值是多少?
int m = -100; int n = 100; Set<Integer> nums = new HashSet<Integer>(); for(int i=0;i<10;i++) { int r = (int)Math.round(Math.random()*(n-m) + m); System.out.println(r); nums.add(Math.abs(r)); } int min = Collections.min(nums); System.out.println("10个 -100到100的随机数 绝对值 的最小值是:"+min);
原创文章,转载请注明出处:https://www.weizhixi.com/article/34.html