模拟 Math.random() 的最大值

Simulate largest value of Math.random()

我正在模拟 Java 中 Math class 的静态 random() 方法,以更好地测试依赖于生成随机数的方法。我使用的代码如下:

@Mock
public double random() {
    return 1.0 - Double.MIN_VALUE;
}

这是我尝试在不相等的情况下尽可能接近 1.0 的值。 (例如 0.999999999999...)

但是,当我调用模拟的 Math.random() 方法时,我总是得到 1.0 作为值。几乎就好像减去 Double.MIN_VALUE 根本不影响 1.0。

为什么 1.0 - Double.MIN_VALUE 的结果是 1.0,如何模拟 Math.random() 的最大可能值?

double 有极限精度。可以表示为双精度的最接近 1.0 - Double.MIN_VALUE 的数字是 1.0。这就是为什么你得到 1.0.

双精度数有 1 位符号位、11 位指数位和 52 位小数位。 (Source)

64位表示的double值为(-1)^sign+1.b51b50...b0 x 2^(e-1023)

最接近 1.0 的是当所有小数位都为 1 且指数为 e-1023==-1 时。 该值在二进制中是 0.1111..111(53 个)。

获取十进制值:

double d = 0.0;
double exp =1.0;
for (int i=1;i<=53;i++) {
  exp=exp*2.0;
  d+=1.0/exp;
}
System.out.println (d);
System.out.println ("d==1.0? " + (d==1.0));

它打印

0.9999999999999999
d==1.0? false

如果您向循环中添加另一个迭代(即 i<=54) 您将得到:

1.0
d==1.0? true

根据 IEEE 754 double 有 15.95 位小数

http://en.wikipedia.org/wiki/IEEE_floating_point

所以如果你尝试 double a = 1e0 - 1e-16 //or less 你会得到 == 1e0

double 不够精确,无法向您显示执行 1.0 - Double.MIN_VALUE 时生成的数字。这是指出here when discussing Java primitive types. You may find this answer interesting as well: