有没有办法避免数组分配?

时间:2014-07-21 18:28:14

标签: arrays memory-management fortran fortran95

我需要单元格索引号,满足以下条件:

    Q(i)<=5 and V(i)/=1

(尺寸(Q)==大小(V))。我写了这样的话:

    program test
    implicit none
    integer, allocatable, dimension(:):: R 
    integer Q(5)
    integer V(5)
    integer counter,limit,i

     counter=0
     limit=5
     V=(/0,0,1,0,0/)
     Q=(/5,10,2,7,2/)

    do i=1,5
      if((Q(i)<=5).AND.(V(i)/=1)) then
          counter=counter+1
      end if
    end do

    allocate(R(counter))
     counter=1
    do i=1,5
      if((Q(i)<=5).AND.(V(i)/=1)) then
          R(counter)=i
          counter=counter+1
    end if
    end do 
    deallocate(R)
    end program test

但我不认为这是非常有效的。这个问题有更好的解决方案吗?

我可以通过编写

删除一个循环
program test
  implicit none
  integer, allocatable, dimension(:):: R
  integer Q(5)
  integer V(5)
  integer counter,limit,i

  counter=0
  limit=5
  V=(/0,0,1,0,0/)
  Q=(/5,10,2,7,2/)
  V=-V+1
  allocate(R((count(V*Q<=5)-count(V*Q==0))))

  counter=1
  do i=1,size(Q)
    if((Q(i)<=5).AND.(V(i)==1)) then
      R(counter)=i
      counter=counter+1
    end if
  end do
end program test

1 个答案:

答案 0 :(得分:0)

问题非常接近duplicate,但解释为什么会是一个繁琐的评论。

该问题的答案利用了一个常见的习语:

PACK((/(i,i=1,SIZE(mask))/), mask)

返回与逻辑数组.TRUE.的{​​{1}}元素对应的基于1的索引的数组。对于该问题,maskmask的结果,但arr.gt.min可以是任何排名第1的逻辑数组。

此处,掩码可能是mask(注意Q.le.5.and.V.ne.1Q的长度相同`。)

在Fortran 95中(这就是我使用V(/../)的原因),人们无法访问自动数组分配的现代功能,因此需要手动分配。像

这样的东西
.ne.

作为使用现代编译器的动机,启用了Fortran 2003合规性,这与

相同
logical mask(5)
mask = Q.le.5.and.V.ne.1
ALLOCATE(R(COUNT(mask))
R = PACK((/(i,i=1,5)/),mask)

(适当的其他声明等)

当考虑在子例程中进行此创建时,如果使用非基于1的索引或子数组,则考虑数组边界非常重要。有关详细信息,请参阅链接问题中的答案。