划分人口Fortran - 接收零

时间:2017-07-06 09:14:53

标签: fortran

我有一个程序来读取和分层具有(x,y)值的多元正态总体的R文件。我想将人口分成两组,其中除法基于x和y是否高于或低于特定数字。

当我在Fortran中进行分层时,我得到的结果是x和y没有结果,就像这样

total number of individuals        1551
   0.00000000       0.00000000          
   0.00000000       0.00000000          
   0.00000000       0.00000000         
   0.00000000       0.00000000           
   0.00000000       0.00000000          
   0.00000000       0.00000000         
   0.00000000       0.00000000          
   0.00000000       0.00000000          
   0.00000000       0.00000000          
   0.00000000       0.00000000          

.
.
.

原始数据如下所示

755,885
656,841
742,844
747,829
776,861
696,809
782,891
771,867
760,826
812,830
711,792
736,840
738,873
793,833
751,836
747,871
796,830
711,868
747,843
758,835
760,824
759,839
696,868

I have attached the file to the original data from R as well

program test 


implicit none

    real, dimension(:), allocatable :: x,y
    real, dimension(:,:), allocatable :: s1, s2, s3, s4
    integer::  io, l1, l2, l3,l4,n,i

    open(33, file = '', status = 'old', action = 'read')
    n = 0 
    DO
        READ(33,*,iostat=io)
        IF (io/=0) EXIT
        n = n + 1
    END DO 

    allocate(x(n) ,y(n)) 
    rewind(33)

    DO i =1,n
        READ(33,*) x(i), y(i)
    END DO

    allocate(s1(n,2))
    allocate(s2(n,2))
    allocate(s3(n,2))
    allocate(s4(n,2))

    s1=0
    s2=0
    s3=0
    s4=0

    l1=1
    l2=1
    l3=1
    l4=1

    do i = 1 , n 
        if (x(i) >=0 .AND. x(i)<=500) then
            if( y(i) >= 0 .AND. y(i) <=500) then
                s1(l1, :)=(/x(i), y(i) /)
                l1=l1+1
            end if 

        else if (x(i)  > 500  .AND.  x(i)  <= 1000 ) then
            if ( y(i) > 0  .AND. y(i) < 500 ) then
                s2(l2, :)=(/x(i), y(i) /)
                l2=l2+1
            end if
        end if

        write(*,*)  s1(l1, :)
    end do !iloop

end program test

我不知道我在这做错了什么。

2 个答案:

答案 0 :(得分:0)

这被称为&#34;悬空的ELSE问题&#34;。 FORTRAN认为&#34;否则if(x(i)&gt; 500 ...&#34;部分属于&#34; if(y(i)&gt; = 0 .AND.y(i) &lt; = 500)&#34;声明。在&#34; else&#34;之前添加&#34; END IF&#34;。

 do i = 1 , n 
    if (x(i) >=0 .AND. x(i)<=500) THEN
        if( y(i) >= 0 .AND. y(i) <=500) THEN 
            s1(l1, :)=(/x(i), y(i) /)
                l1=l1+1
        end if
    else if (x(i)  > 500  .AND.  x(i)  <= 1000 )THEN
        if ( y(i) > 0  .AND. y(i) < 500 ) THEN  
            s2(l2, :)=(/x(i), y(i) /)
                l2=l2+1
        END IF 
    END IF 
END do !iloop

答案 1 :(得分:0)

鉴于您提供的示例数据文件,我认为您获得的输出是正确的。每个案例属于x> 1。 500,y> 500,您的代码不适合将这些条目写入分层。

根据我的理解,以下是您原始问题的解决方案。我已将代码分解为许多子例程,这有助于使其更容易理解。请注意,我的代码中的假设是所有数据都在0 - 1000范围内。

module util
    implicit none
    private

    public :: get_strat
    public :: write_strat

    contains
        function get_strat(x, y) result(strat)
            integer, intent(in) :: x
            integer, intent(in) :: y
            integer :: strat

            integer, parameter :: mid_val = 500

            if (x < mid_val .and. y < mid_val) then
                strat = 1
            else if (x < mid_val .and. y >= mid_val) then
                strat = 2
            else if (x > mid_val .and. y < mid_val) then
                strat = 3
            else 
                strat = 4
            end if

        end function

        subroutine write_strat(trg, strat, x, y)
            integer, intent(in) :: trg
            integer, intent(in) :: strat(:)
            integer, intent(in) :: x(:)
            integer, intent(in) :: y(:)

            integer :: i, count_strat

            count_strat = 0

            write(*, *) "Writing stratification ", trg
            do i = 1, size(x)
                if (strat(i) == trg) then
                    write(*, *) x(i), y(i)
                    count_strat = count_strat + 1
                end if
            end do
            write(*, *) "Total = ", count_strat
            write(*, *)
        end subroutine 
end module util

program test 
    use util
    implicit none

    integer, dimension(:), allocatable :: x,y, strat
    integer::  io, n, i

    open(33, file = 'xyBVNData_R.txt', status = 'old', action = 'read')
    n = 0 

    do 
        read(33, *, iostat=io)
        if( io /= 0) exit 
        n = n + 1
    end do

    allocate(x(n) ,y(n), strat(n)) 
    rewind(33)

    do i = 1, n
        read(33, *) x(i), y(i)
    end do

    do i = 1, n
        strat(i) = get_strat(x(i), y(i))
    end do

    do i = 1, 4
        call write_strat(i, strat, x, y)
    end do

end program test

通过分解这样的代码,可以更容易理解并发现任何逻辑缺陷。例如,在您的代码中,行计数变量l1 ...在找到匹配后递增。这意味着在程序结束时,计数大于匹配条目的数量。更明确的习语是:

l# = 0
...
if (...logic...)
    l# = l# + 1
    !! Do something
end if