为什么java中的generator.nextDouble()只返回0到1之间的值?generator.nextInt()方法要求输入一个限值。为什么Double方法不是这样呢?
发布于 2016-12-21 19:05:40
这个答案有点推测,但我想原因是随机数生成器应该是均匀地返回pseadorandom。均匀地产生双值一点也不简单,因为加倍本身并不是均匀分布的。
忽略符号、双数或浮点数通常都存储在表单m * 2^e中,其中m和e有固定的位宽,m被解释为0 (包括)和1 (独占)之间的数字。这意味着,对于高数字,连续两个双打之间的差异远远大于小数字。因此,简单地用随机比特填充双比特不会产生均匀分布的伪随机数。
相反,解决方案是将指数e固定为0,并且只选择一个随机尾数m,该值在0到1之间产生一个均匀分布的双倍。如果需要在不同的范围内随机加倍,则可以将该数字乘以所需的范围:
double randomDouble = rng.nextDouble() * range;当射程不太高时,这在实践中就足够好了。
发布于 2016-12-21 19:31:47
从概念的角度来看,人们可能会争辩说,从数学意义上讲,0.0到1.0之间的间隔是很好的:给定0.0到1.0之间的随机数,在任意范围内计算一个随机数是很简单的。当然,可以在Random类中插入实用程序方法,实现也同样简单:
public double nextDouble(double min, double max) {
return min + nextDouble() * (max - min);
}现在人们可能会问,为什么这样的方法一开始就不是基本的实现。也就是说,为什么应该基于现有的nextDouble()方法来实现该方法,以及为什么没有方法“直接”生成所需范围内的值。
Hoopje在他的回答中已经指出了一个重要的问题:原因可能是0.0到1.0之间的范围更适合于表示均匀分布的值。
当查看(或者更确切地说是:仔细阅读)有关IEEE 754浮点数格式的详细信息时,您将看到值的密度随着值的增大而减小。
当您启动一个IEEE计算器并输入0.0、1.0和1.70141*10^38的值时,您将看到它们的表示(这里是float -类似于适用于double的语句):
0.0 = 0x00000000 = 0
1.0 = 0x3F800000 = 1065353216
1.7...*10^38 = 0x7EFFFFFE = 2130706430实际上,0.0到1.0之间的浮点数与1.0到17014116317805962800168797686300000.0之间的数字基本相同。实现一个好的、一致的随机数生成器并不容易,考虑到可表示值本身并不是均匀分布的问题,为任意范围创建专用实现是不可能的。
因此,对于0.0到1.0的范围,可以用实心声明值是均匀分布的。对于其他范围,人们将不得不争论什么“统一性”应该实际意味着一个特定的范围.
发布于 2016-12-21 18:40:10
我想让您了解一下API设计的动机。这有点推测,但选择的设计至少有一个很好的理由,即它很容易正确实现,同时仍然可以提供任意大小的随机数(因为您可以缩放结果)。
另一个原因可能是nextDouble()的结果范围遵循了长期以来关于浮点PRNG的惯例。
我理解您发现整数和浮点API之间的区别令人不安,但这绝不是Java (和其他)整数和FP API之间的唯一区别。这两种数字表示法用途完全不同,很少相交。强迫他们拥有类似的API几乎没有什么好处。
https://stackoverflow.com/questions/41269163
复制相似问题