小白转型Java之路--随时记录疑惑 三.简单问题: 如何生成指定范围的随机数

      首先想到的是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)经过加工预计也能达到要求,另外看到

setSeed​(long seed)
Sets the seed of this random number generator using a single  long seed.

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就算一次,重复调用值是一样的



先这样吧,等学完流再解决...

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值