首先想到的是Random类 查询API,JDK9里Random | RandomAccess | RandomAccessFile 可能与之有关,后两项实现list接口 和 读取写入随机访问文件.我们不需要那么复杂功能.
Random :生成伪随机数的流.
构造方法 Random(); ---应该是我们运用的目标 没有参数 很简单 .点进源码(Idea里Ctrl+鼠标左键查看)看了下 大概和现在系统时间有关系
Random(long seed) 点进源码(Idea里Ctrl+鼠标左键查看)看了下 seed具体是什么还是不太清楚.后面再验证.继续解决现在问题
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; } }
@HotSpotIntrinsicCandidate public static native long nanoTime();
public Random(long seed) { if (getClass() == Random.class) this.seed = new AtomicLong(initialScramble(seed)); else { // subclass might have overriden setSeed this.seed = new AtomicLong(); setSeed(seed); } }
private final AtomicLong seed;
public AtomicLong(long initialValue) { value = initialValue; }
private static long initialScramble(long seed) { return (seed ^ multiplier) & mask; }
private static final long multiplier = 0x5DEECE66DL; private static final long addend = 0xBL; private static final long mask = (1L << 48) - 1;
目标明确 生成制定范围的随机数 例如:产生1个随机数 范围要求3到20.
不多说了 具体的查询API ,那么运用无参的构造(因为还不清楚seed是什么),要生成范围要求,看来和调用的方法有关.要返回的是int,那么能排除很多.其中ints(int randomNumberOrigin, int randomNumberBound) Returns an effectively unlimited stream of pseudorandom
int
values, each conforming to the given origin (inclusive) and bound (exclusive).大意 返回一个无限流的有效伪随机int值,每个符合给定的起始(包含)和边界(不包含).符合要求...nextInt(int bound)经过加工预计也能达到要求,另外看到
nextInt(int bound) |
Returns a pseudorandom, uniformly distributed
int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
|
---|
这两个也很感兴趣,不能直接看出怎么用.稍后再研
究
产生1个随机数 范围要求3到20.导包
import java.util.Random; public class TestRandom { public static void main(String[] args) { Random A = new Random(); int m = A.ints(3, 20); System.out.println("m=" + m); } }
发现报错,Error:(7, 23) java: 不兼容的类型: java.util.stream.IntStream无法转换为int.原来是"流"的问题,既然是流的问题能不能通过Integer(int value);的包装类方法来转换?emmm,想了一下 估计不行 但还是试试
int m = Integer.parseInt(A.ints(3, 20));
果然报错了.还没学到流 只是大概知道这是种输出方式...那么就换其他方法实现吧
import java.util.Random; public class TestRandom { public static void main(String[] args) { Random A = new Random(); /* int m = Integer.parseInt(A.ints(3, 20)); System.out.println("m=" + m);*/ for (int i = 0; i < 10; i++) { int n = 3 + A.nextInt(18); //min + A.nextInt(max-min+1) System.out.println("n="+n); } } }
...这种应该可行,并且总结出 min + A.nextInt (max - min +1) 可能通用,又试把条件变成3-8了下for循环100次,又运行几次,发现3出现次数偏低,并不很均等...
import java.util.Random; public class TestRandom { public static void main(String[] args) { Random A = new Random(); /* int m = Integer.parseInt(A.ints(3, 20)); System.out.println("m=" + m);*/ int count = 0; int count1 = 0; int count7 = 0; int count8 = 0; for (int i = 0; i < 100; i++) { int n = 3 + A.nextInt(5); //min + A.nextInt(max-min+1) if (n == 3) count++; if (n == 4) count1++; if (n == 4) count7++; if (n == 4) count8++; System.out.println("n="+n); } System.out.println("n=3共"+count+"次"); System.out.println("n=4共"+count1+"次"); System.out.println("n=7共"+count7+"次"); System.out.println("n=8共"+count8+"次"); } }
运行一次后统计结果:
n=3共20次
n=4共25次
n=7共25次
n=8共25次
运行二次后统计结果:
n=3共17次
n=4共24次
n=7共24次
n=8共24次
运行到第5次 统计结果 n=3 要高于其他的 ,而其他的统计结果几乎一致...
这是什么情况? 通过搜索 有很多前辈也提出了这问题并回答解决了.点击打开链接 回答的比较多 (这种方法并不太好,初始的两个数出现次数要比边界内的其他数出现概率要低,改为 下列 出现的概率要"公平"的多
int n = min + random.nextInt(max+2)%(max-min+1)
)
另外seed自己运行了一下 发现每次的随机数都是一样的 ...
Random r = new Random(100);
int a = r.nextInt();
int b =r.nextInt();
运行后,ab值不同,但运行两次 a b的值不会变化
通过搜索得到一定了解 :大意就是以前计算机内存有限,如果要产生真正的随机数是不具备条件的,设计了利用种子来生成随机数 例如种子是11,进行一系列操作:11平方,121平方,14641平方拼接得到11121146412143588881的数字,计算机每次依次取一位,近似模拟出随机效果
那么得到结论,ab都是利用种子算出来的,每次调用nextInt就算一次,重复调用值是一样的
先这样吧,等学完流再解决...