随机数

Updated: 2019-01-06

入门

下面这些命令可以用来产生随机数。注意每次产生的数都是不一样的,r1r2 也是完全不同的。这也是为什么他们被叫做随机数:不可预测。

jshell> Random r1 = new Random();
r1 ==> java.util.Random@224edc67

jshell> Random r2 = new Random();
r2 ==> java.util.Random@46d56d67

jshell> r1.nextInt(100);
$3 ==> 21

jshell> r2.nextInt(100);
$4 ==> 81

jshell> r1.nextInt(100);
$5 ==> 3

jshell> r2.nextInt(100);
$6 ==> 2

坑!

真的是不可预测吗?那为什么下面这段程序每次产生的都是"hello world"?

import java.util.Random;

class HelloWorld {

    private static String randomString(int i) {
        Random ran = new Random(i);
        StringBuilder sb = new StringBuilder();
        int k = ran.nextInt(27);
        while (k != 0) {
            sb.append((char)('a' - 1 + k));
            k = ran.nextInt(27);
        }
        return sb.toString();
    }

    public static void main(String[] argv) {
        System.out.println(randomString(-229985452) + " " + randomString(-147909649));
    }
}

进阶

程序并不会真的产生随机数。你所看到的都是伪随机数。随机数的一个参数是“种子”,种子相同的情况下产生的随机数序列是确定的:

jshell> Random r1 = new Random(666);
r1 ==> java.util.Random@26653222

jshell> Random r2 = new Random(666);
r2 ==> java.util.Random@3532ec19

jshell> r1.nextInt(100);
$9 ==> 15

jshell> r2.nextInt(100);
$10 ==> 15

jshell> r1.nextInt(100);
$11 ==> 4

jshell> r2.nextInt(100);
$12 ==> 4

jshell> r1.nextInt(100);
$13 ==> 67

jshell> r2.nextInt(100);
$14 ==> 67

那段程序中刚好给定的两个种子可以产生数字序列[8, 5, 12, 12, 15, 0][23, 15, 18, 12, 4, 0],非 0 的部分刚好是helloworld的字母序号,所以把他们转换为字符,打印出来就成了hello world

这个问题在StackOverflow上有讨论。