我不明白为什么这个Fortran程序无法构建

时间:2018-07-13 14:40:23

标签: fortran random-walk

我希望有人能够查看我的夏季项目代码,并让我知道我在哪里搞砸了。这是随机行走,但我做到了,这样当行走者超过6时,它又回到1,反之亦然。另外,当有多个步行者时,程序将确保只有两个最大步行者可以占用相同的“站点”。每当我尝试通过SilverFrost和Geany构建该程序时,它都会失败,而当我使用在线Fortran构建器并使其打印而不是将数据写入文本文件时,它将起作用。错误消息是

  

错误112,引用未定义的变量,数组元素或函数结果(/ UNDEF)主-在dddd.f95文件的第102行[+ 0c8d]

第102行是这样:

position(e,n)=position(e,n)+2

代码如下:

program FiniteRandomWalkWithSites
implicit none
integer :: position(4,1000),n,y,g,m,z,e ! The 2 used in the declaration can be changed in order to create n-number of walkers
real::x,onethird,twothird
real, dimension(1000)::random
onethird=1.00/3.00
twothird=2.00/3.00
do n=1,1000
    position(1,n)=n
end do
do z=2,4 !Despite the fact that this do loop is redundant with just 1 "position column", the ending value ought to be modified to the same value as the one made on line 3
    y=1
    m=0
    do n=1,1000
        call random_number(x)
        random(n)=x
            if (x .le. onethird) then
                m=y+1
                if (m .gt. 6) then
                    m=1
                    y=m
                    position(z,n)=m          
                else if (m .lt. 1) then
                    m=6
                    y=m
                    position(z,n)=m
                else
                    m=m
                    y=m
                    position(z,n)=m
                end if
            else if ((x .gt. onethird) .and. (x .le. twothird)) then
                m=y-1
                if (m .gt. 6) then
                    m=1
                    y=m
                    position(z,n)=m
                else if (m .lt. 1) then
                    m=6
                    y=m
                    position(z,n)=m
                else
                    m=m
                    y=m
                    position(z,n)=m
                end if
            else               
                m=y+0
                if (m .gt. 6) then
                    m=1
                    y=m    
                    position(z,n)=m
                else if (m .lt. 1) then
                    m=6
                    y=m
                    position(z,n)=m
                else
                    m=m
                    y=m
                    position(z,n)=m
                end if
            end if
    end do
end do
jloop:do z=2,4
    ploop:do n=1,1000
        if ((position(z,n) .eq. position(z+1,n)) .and. (position(z,n) .eq. position(z+2,n))) then
            call random_number(x)
            if (z .eq. 2) then            
                if (x .le. onethird) then
                    e=z
                else if ((x .gt. onethird) .and. (x .le. twothird)) then
                    e=z+1
                else
                    e=z+2
                end if
            else if (z .eq. 3) then            
                if (x .le. onethird) then
                    e=z
                else if ((x .gt. onethird) .and. (x .le. twothird)) then
                    e=z+1
                else
                    e=z-1
                end if
            else if (z .eq. 4) then            
                if (x .le. onethird) then
                    e=z
                else if ((x .gt. onethird) .and. (x .le. twothird)) then
                    e=z-1
                else
                    e=z-2
                end if
            end if                                                
        end if
        if (random(n) .le. onethird) then
            if (x .lt. .50) then
                position(e,n)=position(e,n)+1
                if (position(e,n) .gt. 6) then
                    position(e,n)=1
                end if                
            else if (x .gt. .50) then
                position(e,n)=position(e,n)+2
                if (position(e,n) .gt. 6) then
                    position(e,n)=1
                end if                
            end if
        else if ((random(n) .gt. onethird) .and. (random(n) .le. twothird)) then
            if (x .lt. .50) then
                position(e,n)=position(e,n)-1
                if (position(e,n) .lt. 1) then
                    position(e,n)=6
                end if
            else if (x .gt. .50) then
                position(e,n)=position(e,n)-2
                if (position(e,n) .lt. 1) then
                    position(e,n)=6
                end if                
            end if
        else
            if (x .lt. .50) then
                position(e,n)=position(e,n)+1
                if (position(e,n) .gt. 6) then
                    position(e,n)=1
                end if
            else if (x .gt. .50) then
                position(e,n)=position(e,n)-1
                if (position(e,n) .lt. 1) then
                    position(e,n)=6
                end if
            end if
        end if
    end do ploop
end do jloop
do g=1,1000
        print*, position(1,g),position(2,g),position(3,g),position(4,g)!...position(a,g) [where a is rightmost column #]
end do

end program FiniteRandomWalkWithSites

1 个答案:

答案 0 :(得分:0)

  

我不明白为什么该Fortran程序无法构建

简短答案

我也不是。可能是因为它在很多方面都被破坏了。根据编译器和传递的特定编译选项,它可能可能无法编译。在运行时也会可能可能 崩溃


扩展答案

  

错误112,引用未定义的变量,数组元素或函数结果(/ UNDEF)主-在dddd.f95文件的第102行[+ 0c8d]

我的编译器实际上已经编译,但是在运行时给出了更好的错误报告:

  

forrtl:严重(194):运行时检查失败。变量'FINITERANDOMWALKWITHSITES $ E'未在'。\ main.f90(102,17)'中使用

变量e尚未定义就到达程序的这一点。这是什么意思? Fortran Standard调用“已定义” 具有有效值的数据对象。粗略地说,这意味着您在程序运行的任何先前时间都已为此变量分配了一个值。 “也许我在上一个if块中为它分配了一个值!” ,您可能会说。

if ((position(z,n) .eq. position(z+1,n)) .and. (position(z,n) .eq. position(z+2,n))) then
  call random_number(x)
  if (z .eq. 2) then            
    if (x .le. onethird) then
      e=z
  ! (...)
end if

问题是:如果不满足if语句的条件(并且在很多迭代中不满足,取决于生成的随机数),则内部代码将不会执行。如果在第一次迭代中发生这种情况,则您尚未在任何时候通过if构造体,并且e在到达指示的代码行时从未赋予它任何值。错误。

编译器不应在编译时检测到这种错误,这就是为什么它如此奇怪以至于您无法对其进行编译。也许您的编译器可以解析和扫描代码的所有条件分支,并寻找可能未定义的变量。老实说,我从未见过。

但这并不重要。此处重要的是,这是一个 severe 错误,并且您的程序可能会由于访问冲突而崩溃(或者,很不幸,不是),也就是说,当您尝试访问内存地址不是由程序管理的(或写为只读的),有时是由于数组越界问题引起的。

怎么会发生?好吧,默认情况下,Fortran不在运行时检查数组索引。您应该在代码时间这样做。如果e是未定义的(并且您没有指定未定义变量的检查作为编译器选项),而您尝试使用它,则它的值可能包含一些已在其使用的内存地址上设置的垃圾值。这是潘多拉盒子,用于各种不可预测的行为。例如,如果e的值为0,则position(e,n)=position(e,n)+2会尝试查找数组的列0(可以是系统的任何其他内存地址)并尝试写入/读取它。如果不崩溃,则会产生错误的结果。


解决方案

在您的else构造中添加一个if子句,该子句通常将值设置为e。它将是什么值取决于您的程序逻辑-您将自己弄清楚。

if ((position(z,n) .eq. position(z+1,n)) .and. (position(z,n) .eq. position(z+2,n))) then
  call random_number(x)
  if (z .eq. 2) then            
    if (x .le. onethird) then
      e=z
  ! (...)
else
  e = some value that makes sense for your program
end if

现在一切都好吗?

呃...不。您应该真正查看所有程序逻辑和结构,然后进行调试。有很多细节要解决。例如,当数组的形状为position(z+1,n)时,您将在position(z+2,n)的循环中执行z=2,4(4,np)z=3z=4会发生什么?您可能应该在call random_number(x)之前初始化随机种子。另外,您可以通过不对数组维数或其他参数进行硬编码来查看诸如使算法更抽象等内容。

我强烈建议您在开发代码时打开所有用于检查和警告的编译选项,特别是检查未定义的变量和边界检查。