遇到的随机数问题

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遇到的随机数问题相关的知识,希望对你有一定的参考价值。

随机数

最近老是看到生成随机数,随机打乱的面经
来自己总结一下

Random的实现原理

首先看java里面的Random是怎么实现的

看到这里有一个原子类的seed,和两个16进制不可变的值,还有一个mask,47位1

然后无参构造函数,调用的这两个函数就是为了生成一个随机的值:

无参构造,调用的是有参构造函数,用来初始化seed的值

然后看一下常用的生成随机整数的方法,调用的是next()

然后看next(),里面的逻辑就是,获取到seed种子,然后生成的下一个种子nextseed就等于下面这个公式计算出来的一个值,虽然muliplier和addend的值不知道怎么取的,但是可以看出这个随机其实也是一个伪随机的

另外,给定一个边界生成随机数
如果给定的边界正好是一个2的幂次方,那么就直接移位
如果不是2的幂,那么就取余r = u % bound

产生高强度的随机数,有两个重要的因素:种子和算法。算法是可以有很多的,通常如何选择种子是非常关键的因素。 如Random,它的种子是根据时间来实现的,所以它的随机数都是可预测的, 是弱伪随机数。
强伪随机数的生成思路:收集计算机的各种信息,键盘输入时间,内存使用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,主要是达到不可预测性。

这篇文章说的比较详细:
https://my.oschina.net/hosee/blog/600392

将数组随机打乱

我想到的方法就是产生一个随机数,然后对数组中元素个数n取余数,所得的数就是本次随机的位置
然后取出这个元素,放在结果数组的第一个位置
然后继续产生随机数对n - 1取余数,得到第二个位置
以此类推,生成一个随机的结果数组

然后去查了一下,发现更好的方法是遍历一遍数组,
产生一个随机数,对n取余后,得到一个下标idx
然后与i位置的元素交换

		Random random = new Random(6);

        int[] nums = {1,2,3,4,5,6};
        for(int i = nums.length; i >= 1; i--){
            int idx = random.nextInt(i);
			//swap
            int temp = nums[i - 1];
            nums[i - 1] = nums[idx];
            nums[idx] = temp;
        }

还有一种是用排序的方法,这个可能不太严谨,但是要get到这个思想
具体见:https://www.cnblogs.com/macq/p/6650586.html

		List<Integer> list = new ArrayList<>();
        for(int i = 1; i < 10; i++){
            list.add(i);
        }
        Collections.sort(list, (a, b) -> (Math.random() - 0.5) > 0 ? 1 : -1);
        System.out.println(list);

以上是关于遇到的随机数问题的主要内容,如果未能解决你的问题,请参考以下文章

Wagtail - 在页面上呈现带有相关片段和标签的数据时遇到问题

多臂强盗:当随机概率低于分配给强盗的成功概率时,为什么我们将奖励增加1

21个常用代码片段

java获取随机时间的源码片段

PHP 代码片段

如何在Sublime Text中添加代码片段