【发布时间】:2018-09-25 14:20:40
【问题描述】:
在闭区间 [0,1] 而不是通常的 [0,1) 中生成伪随机数的最佳方法是什么?我想出的一个想法是拒绝(1/2,1)中的值,然后将数字加倍。不知道有没有更好的方法。
real x
do
call random_number(x)
if (x <= 0.5) exit
end do
x = 2*x
print *, x
end
最重要的要求是算法不应该做出比random_number()生成的分布更差的分布(在均匀性和相关性方面)。我也喜欢简单。 random_number() 的包装器会非常好,我不打算实现一个全新的生成器。
正如@francescalus 在 cmets 中指出的那样,使用上述算法,[0,1] 中的大量数字出现的概率为零。下面的代码实现了一种稍微不同的方法:将区间扩大一点,然后去掉超过 1 的值。它应该在这方面表现更好。
real x
do
call random_number(x)
x = x*(1 + 1e-6)
if (x <= 1.) exit
end do
print *, x
end
【问题讨论】:
-
"Best" 太宽泛了,所以也许您可以解释一下您在这个新发行版中需要哪些属性。例如,在问题的情况下,区间 [0,1] 中的许多数字现在出现的概率为零。
-
@francescalus 最重要的要求是它不应该“破坏”
random_number()生成的分布。我不想实现一个全新的生成器,只是想把random_number()包装进去。我希望它简洁。从第一个要求来看,如果我正确理解第一个算法的问题,我添加的第二个算法应该会更好。 -
@ArchStanton wiki 页面提到了根据 U(0,1) 生成的随机数,这并不意味着必须包含 1。我还认为该页面的限制有点混乱。如果您查看数字食谱,它会得到很好的解释。简而言之,您可以毫无问题地使用
random_number进行 Box-Muller 变换。你会得到一个非常好的高斯分布。 -
4个均匀分布U((0,1))、U([0,1))、U((0,1])和U([0,1)的累积分布函数]) 是相同的,所以你担心的东西实际上什么都不是。
-
@kvantour 包含 1 不会伤害(代价是在 [0,1) 中排除一些其他可表示的实数),但是任何明确使用的代码它的包含(例如,通过显式测试与 1 的相等性)可能是错误代码(恕我直言)。