Java 如何从SplittableRandom获取nextFloat()?
自从听说java的SplittableRandom以来,我一直在使用它,因为它速度快,而且不需要多线程。然而,尽管它几乎拥有Random类中的所有方法,但它并没有附带Java 如何从SplittableRandom获取nextFloat()?,java,random,floating-point,Java,Random,Floating Point,自从听说java的SplittableRandom以来,我一直在使用它,因为它速度快,而且不需要多线程。然而,尽管它几乎拥有Random类中的所有方法,但它并没有附带nextFloat()。为什么 现在,真正的问题是,接下来我将如何创建nextFloat方法?查看double如下所示:(来自JDK 8) 因此,如果我没有移位的经验(我想是使用epsilon),我怎么能实现我想要的呢?你需要首先理解这条线背后的含义: double longBitsToDouble = (this.nextLong
nextFloat()
。为什么
现在,真正的问题是,接下来我将如何创建nextFloat
方法?查看double
如下所示:(来自JDK 8)
因此,如果我没有移位的经验(我想是使用epsilon),我怎么能实现我想要的呢?你需要首先理解这条线背后的含义:
double longBitsToDouble = (this.nextLong() >>> 11) * 1.1102230246251565E-16;
this.nextLong()
返回一个64长的字符串>>11
将long
改为unsigned并删除最后11位,现在我们得到一个53位的随机值。这也是double
的精度*1.1102230246251565E-16
。这相当于1/9007199254740992.0
,或2-53longBitsToDouble
是一个从0(包括)到1(排除)的随机统一的double
与浮点
相比,它的精度是24位,而this.nextInt()
生成32位随机值,因此对应的行应写为
float intBitsToFloat = (this.nextInt() >>> 8) * 5.960464477539063E-8f;
(除了十进制表示法5.960464477539063E-8f
之外,您还可以使用,这对读者来说可能更清楚:
float intBitsToFloat = (this.nextInt() >>> 8) * 0x1.0p-24;
)在我看来,如果不深入考虑这个问题的数学原理,您可以使用该方法在所需的范围内生成一个
双精度
,然后将结果强制转换为浮点。此外,在缩放数字范围时,模运算符不是更快吗,至少当涉及到大数字时?这样做有什么原因吗?看看你为什么不使用?谢谢@kennytm。我仍然会尝试使用它,因为它显然加快了生成更大的数字的速度。至于为什么该函数不存在,可能是因为float
不是新的Java 8功能所要支持的类型之一(例如,没有FloatStream
或FloatConsumer
等)。新功能的头等公民是int
、long
和double
(有时是boolean
)。谢谢!这澄清了很多事情。为了确定,在这种情况下,1/2^(-53)应该是1/2^(-23)还是1/2^(-15)?@jetp250两者都不是,它是2^-24。是的,但为什么?当然,这更容易,但它也稍微慢了一点,因为它必须将64位双精度浮点转换为32位浮点。这样我就再也学不到什么新东西了:)@jetp250我非常感谢你的求知欲。不过,关于堆栈溢出的问题通常是在假设您有生产代码可以工作的情况下回答的。在这种情况下,滚动自己的低级数学例程通常不是一个好主意。如果你的情况不同,也许值得在你的问题中指出。不过,我不会担心演出。我怀疑你是否能够在你的应用程序中测量它,如果这种微优化是一个问题,那么Java可能是一个错误的技术开始。谢谢@5gon12eder!关于表演;是的,这是我一直非常关心的事情,一切都必须尽可能顺利地进行。我承认这不是最好的品质。然而,在这种情况下,我将不得不使用java,我使用的整个库只存在于java中,我怀疑它是否会被移植到任何其他语言。然而,我确实对一些C语言感兴趣!
double longBitsToDouble = (this.nextLong() >>> 11) * 1.1102230246251565E-16;
float intBitsToFloat = (this.nextInt() >>> 8) * 5.960464477539063E-8f;
float intBitsToFloat = (this.nextInt() >>> 8) * 0x1.0p-24;