在闭区间[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在评论中指出的那样,通过上述算法,[0,1]中的许多数字将出现的可能性为零。以下代码实现了一种略有不同的方法:将间隔扩大一点,然后切出超过1的值。在这方面应该表现得更好。
real x
do
call random_number(x)
x = x*(1 + 1e-6)
if (x <= 1.) exit
end do
print *, x
end
答案 0 :(得分:3)
交换x和1-x怎么样?抱歉,我的Fortran生锈了
real function RNG()
real :: x
logical, save :: swap = .TRUE.
call random_number(x)
if (swap .EQV. .TRUE.)
RNG = x
swap = .FALSE.
else
RNG = 1.0 - x
swap = .TRUE.
end if
end
如果您想使用Box-Muller,请在任何地方使用1-U,它应该可以工作
z0 = sqrt(-2.0*log(1.0-U1))*sin(TWOPI*U2)
z1 = sqrt(-2.0*log(1.0-U1))*cos(TWOPI*U2)
与Box-Muller的拒绝版本相同