关于js && java 的随机数问题
最近在JAVA课上提到了个随机数的问题,用的是Random对象的nextInt() 方法。然后就对随机数这个概念产生了兴趣,就对此查询了些资料文档,写了点自己的理解。
随机数是由算法生成的,然而算法的五大特性中的确定性又决定,固定的输入只能有固定的输出,那么问题来了。所谓的随机数都非是真正的随机,只是在一定输入下的固定输出而已,因此为了实现随机,就只能在算法的输入上想方法,一般来说是获取系统时间作为种子值,准确值在ms。
亦或是在元器件上的随机做文章,比如实时的电压,电流等。
那自然界有没有真正的随机呢,在自然宏观上似乎也没有真正的随机,在人类可知的情况比如抛硬币,丢骰子,天气等。在可知的各种情况下,这些结果都是可以确定的。
这个时候,我想到了薛定谔的猫。我便对量子力学的随机进行了一番查询,贝尔提出了一个实验可观测的效应来区分真随机还是伪随机,也就是贝尔不等式。证明了量子力学下存在真随机,但是有一种观点认为,我们当前维度观察到的随机是真随机,在更高维度下还是这样吗? 从科学的曲折前进来看,我赞同后一种。假设成立的话,那!往下走的话,问题又来了,真正的的随机存在吗?这里只是做一个门外汉的围观而已。
JS随机数
ECMAScript没有规定死要用什么算法来实现Math.random(),只规定了返回值的范围。
ECMAScript Language Specification
random ( )
Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments.
因此不同的浏览器引擎实现的随机数的方法不尽相同。
我查询了一下 chrome V8引擎的实现方法
function MathRandom() {
var r0 = (MathImul(18030, rngstate[0] & 0xFFFF) + (rngstate[0] >>> 16)) | 0;
rngstate[0] = r0;
var r1 = (MathImul(36969, rngstate[1] & 0xFFFF) + (rngstate[1] >>> 16)) | 0;
rngstate[1] = r1;
var x = ((r0 << 16) + (r1 & 0xFFFF)) | 0;
// Division by 0x100000000 through multiplication by reciprocal.
return (x < 0 ? (x + 0x100000000) : x) * 2.3283064365386962890625e-10;
}
// Non-standard extension.
function MathImul(x, y) {
return %NumberImul(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y));
}
安利两篇博文吧,等下次再来完善。
Chrome V8引擎系列随笔 (1):Math.Random()函数概览
There’s Math.random(), and then there’s Math.random()
JAVA随机数
JAVA中调用随机数的方法有两种。
- 一个是实例化一个Random对象,调用Random对象的方法。
- 还有一种调用公用对象Math.random()。Math.random()实际上也是调用的Random对象实现。
而JAVA的random对象实现随机数是通过线性同余方程实现的,并且传入的种子值是当前系统的时间。
线性同余生成器(LCG, Linear Congruential Generator)
生成的伪随机数序列最大周期m,范围在0到m-1之间。要达到这个最大周期,必须满足
- c与m互质
- a-1可以被m的所有质因数整除
- 如果m是4的倍数,a - 1也必须是4的倍数
在网上普遍选择的三个参数为9301,49297,233280
random对象所属方法列表
- protected int next(int bits):生成下一个伪随机数。
- boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值。
- void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
- double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布的 double值。
- float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布float值。
- double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的double值,其平均值是0.0标准差是1.0。
- int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
- int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在(包括和指定值(不包括)之间均匀分布的int值。
- long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
- void setSeed(long seed):使用单个 long 种子设置此随机数生成器的种子。
参考资料: