Random 如何在fortran中生成一个随机函数,将相同的随机分布生成数组?

Random 如何在fortran中生成一个随机函数,将相同的随机分布生成数组?,random,fortran,fortran90,Random,Fortran,Fortran90,我想我下面的代码并没有给出相同的随机分布 subroutine trig_random_value() implicit none integer :: t, z, y, x real(real64) :: theta, r real(real64), parameter :: PI=4.D0*DATAN(1.D0) integer, dimension(12) :: date_time integer, dimension(12) :: see

我想我下面的代码并没有给出相同的随机分布

subroutine trig_random_value()
    implicit none
    integer :: t, z, y, x
    real(real64) :: theta, r
    real(real64), parameter :: PI=4.D0*DATAN(1.D0)

    integer, dimension(12) :: date_time
    integer, dimension(12) :: seed

    call date_and_time(values=date_time)
    call random_seed
    seed = date_time(6) * date_time(7) + date_time(8)
    call random_seed(put = seed)

    do z = 1, z_size
        do y = 1, y_size
            do x = 1, x_size

                theta = rand()*2*PI
                r = 0.1*rand()
                l1(1, z, y, x) = r*cos(theta)
                l2(1, z, y, x) = r*sin(theta)

                theta = rand()*2*PI
                r = 0.1*rand()
                l1(2, z, y, x) = r*cos(theta)
                l2(2, z, y, x) = r*sin(theta)

            end do
        end do
    end do

    return
end subroutine trig_random_value
根据我的代码,我尝试将随机值设置为
l1(1,:,:,:,:)
l1(2,:,:,:,:)
l2(1,:,:,:,:,:)
,其中l(t,x,y,z)是(3+1)维数组

为什么我要用三角函数作为随机函数?因为我想要一个循环随机化。如果我绘制l1(1,:,:,:,:)与l2(1,:,:,:)或l1(2,:,:,:,:)与l2(2,:,,:,:)的分布,我将得到半径为0.1的圆形分布

那么,为什么我告诉你,这不完全是给我一个相同的分布?因为我试图测量它们的方差,结果

 variance_l1_t1 =   1.6670507752921395E-003
 variance_l1_t2 =   3.3313151655785292E-003
 variance_l2_t1 =   4.9965623815717321E-003
 variance_l2_t2 =   6.6641054728288360E-003
请注意,(方差_l1_t2-方差_l1_t1)=(方差_l2_t1-方差_l1_t2)=(方差_l2_t2-方差_l2_t1)=0.00166

这是一个很奇怪的结果。实际上我应该得到几乎相同的方差值
l1(1,:,:,:)
l1(2,:,:,:,:)
l2(1,:,:,:,:)
,如果这个函数是好的随机函数。可能是我做错了什么

如何解决这个问题

请求提供的其他信息:

real(real64) function find_variance(l)
    implicit none
    real(real64), dimension(z_size, y_size, x_size), intent(in) :: l
    integer :: z, y, x
    real(real64) :: l_avg = 0
    real(real64) :: sum_val = 0

    do z = 1, z_size
        do y = 1, y_size
            do x = 1, x_size

                l_avg = l_avg + l(z, y, x)

            end do
        end do
    end do

    l_avg = l_avg/(z_size*y_size*x_size)

    do z = 1, z_size
        do y = 1, y_size
            do x = 1, x_size

                sum_val = sum_val + (l(z , y, x) - l_avg)**2

            end do
        end do
    end do

    find_variance = sum_val/(z_size*y_size*x_size)

    return
end function find_variance

在现代Fortran语言中,变量的初始化,如

real(real64) :: sum_val = 0
表示
sum\u val
是一个具有
SAVE
属性的变量(类似于C中的
static
),在程序启动时仅初始化一次。相当于

real(real64), save :: sum_val = 0
SAVE
ed变量的值在整个运行期间保持不变,不会再次初始化为0。要解决此问题,只需更换

real(real64) :: sum_val       !! this is a usual local variable
sum_val = 0                   !! or sum_val = real( 0, real64 )
那我想应该没问题。有关更多详细信息,请参阅。
在我看来,这是Fortran的一个非常令人困惑的特性…

@roygvib求和
(l(z,y,x)-l_avg)**2
除以
N
(在这种情况下
N
x_size*y_size*z_size
)编辑:在你的问题中,用完整的代码来计算方差_l1_t1,方差_l1_t2等应该非常有用,因为如果他们有一些问题,这与随机数是不同的。你的0.1是默认(单一)实数。将
real64
D0
DATAN
相结合是很奇怪的,但不应立即导致问题。顺便说一句,如果您使用Fortran 2008中的功能,我不会使用标记Fortran 90。我一直认为Fortran初始化的这种语法确实有问题…任何解决方案,请使用,我只需要一个正确的输出。你可以复制上面的代码,并尝试检查差异。上帝。。。我以前就知道这件事,但这是我的疏忽。非常感谢您@royvib
sum_val
不是一个自动对象,只是一个普通的本地对象。@francescalus我检查了这个页面,它还说调用
sum_val
automatic..(因为F77默认为静态)。我相应地改变了这个词。谢谢:)