我使用Mersenne Twister实现,为我提供双精度数字。
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/FORTRAN/fortran.html(由Tsuyoshi Tada在Fortran 77中实现,我使用genrand_real2)
但是,我的应用程序需要为了避免警告,同时将数字乘以不同的精度,单个精度随机数。 所以,我写了一个小函数来转换两种数据类型:
function genrand_real()
real genrand_real
real*8 genrand_real2
genrand_real = real(genrand_real2())
return
end
我使用真实和真实的* 8来与我正在处理的代码保持一致。 它在大多数时候都能很好地工作(除了我不确定real()有多快),但是它改变了我的RNG的上限,因为转换将[0,1]更改为[ 0,1]。在我遇到问题之前,我从未想过这件事。
我的问题是,如何以有效的方式确保上限,或者甚至如何编写类似于genrand_real2(原始的)的函数,它为我提供单精度实数。我的猜测是我只需要替换除数4294967296.d0,但我不知道用哪个数字
function genrand_real2()
double precision genrand_real2,r
integer genrand_int32
r=dble(genrand_int32())
if(r.lt.0.d0)r=r+2.d0**32
genrand_real2=r/4294967296.d0
return
end
答案 0 :(得分:1)
您发布的函数不会生成随机数,它只会将随机整数(从genrand_int32()
)限制为区间[0,1]除以2 ^ 32(正好是4294967296)或添加2 ^ 32首先是int是否定的。 2 ^ 32是标准整数可以容纳的值的数量,一半是负数,一半是正数(大约是,正端有1个缺失),因此来自函数genrand_int32()
。
想象一下,你有从-10到10的数字,并希望将它们限制在[0,1]区间。最简单的解决方案是在负数上加20(所以正数为0-10,负数为10-20),然后除以20。 这正是函数正在做的事情,只有2 ^ 31而不是10。
如果您想知道为什么函数的间隔为[0,1]: 由于数字0也需要一个点,并且位表示只能存储2 ^ 32个数字,你不能有2 ^ 31个负数和2 ^ 31个正数和0。解决方法是省略值+ 2 ^ 31(最高正数)因此从你的间隔中排除1。
所以要把整个事情归结为单一的预测:
function genrand_real2()
real genrand_real2,r
integer genrand_int32
r=real(genrand_int32())
if(r.lt.0)r=r+2**32
genrand_real2=r/4294967296
return
end
神奇数字必须保持不变,因为它们与整数相关,而不是实数。
修改强>:
你已经自己说过了,所以我只是为其他人重复:为了便于携带,在技术上不使用默认类型而不指定精度是个好主意。因此,您应该在某处sp = selected_real_kind(6, 37)
(sp
获得单精度),然后real(kind=sp)...
和2.0_sp
等等。
然而,这更像是一个学术观点。