将双精度舍入到单精度:强制上限

时间:2016-06-15 14:10:40

标签: random fortran rounding fortran77 mersenne-twister

我使用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

1 个答案:

答案 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等等。 然而,这更像是一个学术观点。