math.random 在 Java 中的分布是怎样的?
What is the distribution of math.random in Java?
我想在 Java 程序中使用 math.random()。
这种获得双打的方式分布情况如何?
这记录在 Java SE API docs:
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
文档继续提到它在幕后使用 java.util.Random
,大概是 nextDouble()(尽管没有明确说明)。
关于nextDouble中不均匀性的说明如下:
The method nextDouble is implemented by class Random as if by:
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
}
The hedge "approximately" is used in the foregoing description only because the next method is only approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen bits, then the algorithm shown would choose double values from the stated range with perfect uniformity.
看来 non-uniformity 只是由于 next
的潜在不均匀性,而不是 nextDouble 算法本身的重大偏差:
[In early versions of Java, the result was incorrectly calculated as:
return (((long)next(27) << 27) + next(27))
/ (double)(1L << 54);
This might seem to be equivalent, if not better, but in fact it
introduced a large nonuniformity because of the bias in the rounding of floating-point numbers: it was three times as likely that the low-order bit of the significand would be 0 than that it would be 1! This nonuniformity probably doesn't matter much in practice, but we strive for perfection.]
注意,这里是从区间[0,1]统一绘制的,分成2-53等步长,也就是不是等同于从0到1之间的所有double
值的集合中统一抽取。这是一个细微的区别:所有double
值的集合如图所示,0 和 1 本身在数轴上的间隔不均匀:
图片转自docs.oracle.com
我想在 Java 程序中使用 math.random()。
这种获得双打的方式分布情况如何?
这记录在 Java SE API docs:
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
文档继续提到它在幕后使用 java.util.Random
,大概是 nextDouble()(尽管没有明确说明)。
关于nextDouble中不均匀性的说明如下:
The method nextDouble is implemented by class Random as if by:
public double nextDouble() { return (((long)next(26) << 27) + next(27)) / (double)(1L << 53); }
The hedge "approximately" is used in the foregoing description only because the next method is only approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen bits, then the algorithm shown would choose double values from the stated range with perfect uniformity.
看来 non-uniformity 只是由于 next
的潜在不均匀性,而不是 nextDouble 算法本身的重大偏差:
[In early versions of Java, the result was incorrectly calculated as:
return (((long)next(27) << 27) + next(27)) / (double)(1L << 54);
This might seem to be equivalent, if not better, but in fact it introduced a large nonuniformity because of the bias in the rounding of floating-point numbers: it was three times as likely that the low-order bit of the significand would be 0 than that it would be 1! This nonuniformity probably doesn't matter much in practice, but we strive for perfection.]
注意,这里是从区间[0,1]统一绘制的,分成2-53等步长,也就是不是等同于从0到1之间的所有double
值的集合中统一抽取。这是一个细微的区别:所有double
值的集合如图所示,0 和 1 本身在数轴上的间隔不均匀:
图片转自docs.oracle.com