我在Fortran 95中的随机数生成器出了什么问题?

时间:2015-04-02 21:34:07

标签: random fortran gfortran

这是一个randon数字生成器模块,我用它来编译我的主程序(这里没有列出) 当我尝试编译我的随机数生成器模块以查看它是否有效时,我收到以下消息:

  第61行

:调用random_seed(put = seed)   错误:'random_seed'内在的'put'参数的大小太小< 4/12>

这是什么意思?我该如何解决?

module random_angle
 contains
 0
    integer Function random_integer (N)         ! return a random integer between 1 and N
        integer, intent(in) :: N
        real*8 :: x

        call random_number(x)
        random_integer = floor(real(N)*x)+1

    end function random_integer

    Real*8 Function gasdev()           !  ch7.pg.280:gaussian distribution function using ran1 as random # generator

        implicit none
!       integer, intent(inout) :: idum
        integer, save::iset
        real*8:: fac,rsq,v1,v2
        real*8, dimension(2) :: x
        real*8, save :: gset

!       if (idum.lt.0) iset=0
        if (iset.eq.0) then
          rsq = 0.0
          do while (rsq > 1.0.or.rsq==0)  
            call random_number(x)
            v1=2.*x(1)-1
            v2=2.*x(2)-1
            rsq=v1**2+v2**2
!    print *, v1, v2,rsq
          end do    

          fac=sqrt(-2.*log(rsq)/rsq)
          gset=v1*fac
          gasdev=v2*fac
          iset=1
        else
            gasdev=gset
            iset=0
        endif

        return

    end Function gasdev

    real*8 function NormalRandom (average, stddev)
        implicit none
        real*8, intent(in):: average, stddev
        NormalRandom = average + stddev*gasdev()

    end function NormalRandom

    subroutine setSEED (seed)
        implicit none

        real*8:: x
        integer, dimension(4), intent(inout):: seed
        if (seed(1) == 0.0) &
            seed = floor(1000*secnds(0.0)) +(/0, 37, 74, 111 /)  
        call random_seed( put=seed)

    end subroutine setSEED

end module random_angle

1 个答案:

答案 0 :(得分:6)

当编译器说

  

错误:'random_seed'内在的'put'参数的大小太小< 4/12>

这意味着变量seed的大小太小。

在这种情况下,您的seed大小为4(我猜编译器必须期望(至少)12)。

数组的大小必须是一定的大小,这取决于编译器。您可以通过使用另一个参数

调用random_seed来便携地确定所需的大小
integer seed_size
integer, allocatable :: seed(:)

call random_seed(size=seed_size)
allocate(seed(seed_size))
seed = ...
call random_seed(put=seed)

正如Vladimir F在评论中指出的那样,gfortran文件本身has an example采用了这种方法。

如果您不关心便携式设备,可以使用大小为12的数组,并选择值。


作为更高级的阅读,我会说另一件事。我上面给出的例子与你的代码不太相似。也就是说,你说种子设置子程序的输入保证至少是4的大小,它可能包含或不包含你想用作种子的值。

如上所述,您可以将其更改为12,但这不可移植。如果你想要便携,事情变得更加尴尬。

integer, dimension(4), intent(inout):: seed

具有伪参数的大小为4的显式形状数组。主程序中的实际参数是至少该大小的数组。但是,这个大小是规范表达式,唉,call random_seed(size=seed_size)没有给我们在规范表达式中可以使用的东西。

也许像

subroutine setSEED (seed)
  integer, allocatable, intent(inout) :: seed(:)
  integer seed_size

  ! Determine the correct size for the seed
  call random_seed(size=seed_size)

  ! If our seed isn't set, or is too small, kill it.
  if (ALLOCATED(seed)) then
    if (SIZE(seed)<seed_size.or.seed(LBOUND(seed,1))==0.) deallocate(seed)
  end if

  ! If seed isn't allocated (perhaps we killed it because it was too small)
  ! then allocate it to the correct size and initialize it.
  if (.not.ALLOCATED(seed)) then
    allocate(seed(seed_size))
    seed = ...  ! Our fallback seed initialization
  end if

  ! Finally, put the seed.  Using one we set, or the one originally given.
  call random_seed(put=seed)

end subroutine

当然,这要求实际参数为allocatable,但如果您正在处理便携式种子设置,这是一件好事。