关于js && java 的随机数问题

最近在JAVA课上提到了个随机数的问题,用的是Random对象的nextInt() 方法。然后就对随机数这个概念产生了兴趣,就对此查询了些资料文档,写了点自己的理解。

随机数是由算法生成的,然而算法的五大特性中的确定性又决定,固定的输入只能有固定的输出,那么问题来了。所谓的随机数都非是真正的随机,只是在一定输入下的固定输出而已,因此为了实现随机,就只能在算法的输入上想方法,一般来说是获取系统时间作为种子值,准确值在ms。

亦或是在元器件上的随机做文章,比如实时的电压,电流等。

那自然界有没有真正的随机呢,在自然宏观上似乎也没有真正的随机,在人类可知的情况比如抛硬币,丢骰子,天气等。在可知的各种情况下,这些结果都是可以确定的。

这个时候,我想到了薛定谔的猫。我便对量子力学的随机进行了一番查询,贝尔提出了一个实验可观测的效应来区分真随机还是伪随机,也就是贝尔不等式。证明了量子力学下存在真随机,但是有一种观点认为,我们当前维度观察到的随机是真随机,在更高维度下还是这样吗? 从科学的曲折前进来看,我赞同后一种。假设成立的话,那!往下走的话,问题又来了,真正的的随机存在吗?这里只是做一个门外汉的围观而已。

贝尔的论文 1972
贝尔的论文 1982


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 种子设置此随机数生成器的种子。

参考资料:

random下属方法

线性同余方程