如何从SplittableRandom获取nextFloat()?

时间:2017-03-19 15:58:31

标签: java random floating-point

自从我听说它以来,我一直在使用java的SplittableRandom,因为它速度快,而且不需要多线程。但是,虽然几乎所有来自Random类的方法都没有nextFloat()。为什么?

现在,真正的问题是,我将如何创建nextFloat方法呢?看到double生成如下:(来自JDK 8)

final double internalNextDouble(final double n, final double n2) {
    double longBitsToDouble = (this.nextLong() >>> 11) * 1.1102230246251565E-16;
    if (n < n2) {
        longBitsToDouble = longBitsToDouble * (n2 - n) + n;
        if (longBitsToDouble >= n2) {
            longBitsToDouble = Double.longBitsToDouble(Double.doubleToLongBits(n2) - 1L);
        }
    }
    return longBitsToDouble;
}

..我希望我能用以下内容将其转换为32位数字生成;

final float internalNextFloat(final float min, final float max) {
    float intBitsToFloat = (this.nextInt() >>> 11) * 1.1102230246251565E-16f;
    if (min < max) {
        intBitsToFloat = intBitsToFloat * (max - min) + min;
        if (intBitsToFloat >= max) {
            intBitsToFloat = Float.intBitsToFloat(Float.floatToIntBits(max) - 1);
        }
    }
    return intBitsToFloat;
}

然而,这会返回0.000000。我只能假设它溢出某处,在这种情况下我很确定问题出在以下几行:

(this.nextInt() >>> 11) * 1.1102230246251565E-16f;

所以,没有经历过转移(我猜想使用epsilon),我怎么能达到我的目的呢?

2 个答案:

答案 0 :(得分:2)

在没有深入思考这个数学的情况下,在我看来,您可以使用nextDouble方法在所需范围内生成double,然后将结果转换为{{ 1}}。

答案 1 :(得分:1)

你需要先了解这一行背后的含义:

double longBitsToDouble = (this.nextLong() >>> 11) * 1.1102230246251565E-16;
  1. this.nextLong()返回64长。
  2. >>> 11long转为无符号并删除最后11位,因此现在我们得到一个53位随机值。这也是double的精确度。
  3. * 1.1102230246251565E-16。这相当于1 / 9007199254740992.0或2 -53
  4. 所以longBitsToDouble是从0(含)到1(不包含)的随机统一double

    float相比,其精度为24位,而this.nextInt()生成32位随机值,因此相应的行应写为

    float intBitsToFloat = (this.nextInt() >>> 8) * 5.960464477539063E-8f;
    

    (而不是十进制表示法5.960464477539063E-8f,您也可以使用hexadecimal float,这可能会让读者更清楚:

    float intBitsToFloat = (this.nextInt() >>> 8) * 0x1.0p-24;