【问题标题】:Is there a way to avoid an array allocation?有没有办法避免数组分配?
【发布时间】:2014-07-21 18:28:13
【问题描述】:

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

    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

【问题讨论】:

  • 你的意思是像stackoverflow.com/q/21208593/3157076这样的吗?
  • 是的,这和我的问题类似,但它也使用“可分配”。也许是“链表”?是不是更实用的解决方案?
  • 一个可以使用链表,但这很可能会使用更多涉及的动态内存管理。对于像这样的简单情况,我倾向于根据“我编写正确代码需要多长时间”来衡量“效率”。在这种情况下,另一个问题的答案 - 将两个循环降低到一行 - 这样做。如果您有其他考虑,请在问题中详细说明。
  • 你的意思是删除一个循环吗?我做了一些改变:程序测试隐式无整数,可分配,维度(:)::R整数Q(5)整数V(5)整数计数器,限制,i counter=0 limit=5 V=(/0,0,1,0,0/) Q=(/5,10,2,7,2/) V=-V+1 allocate(R((count (VQQ==0)))) counter=1 do i=1,size(Q) if((Q(i)

标签: arrays memory-management fortran fortran95


【解决方案1】:

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

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

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

这将返回一个从 1 开始的索引数组,对应于逻辑数组 mask.TRUE. 元素。对于那个问题,maskarr.gt.min 的结果,但 mask 可以是任何 rank-1 逻辑数组。

这里,掩码很可能是Q.le.5.and.V.ne.1(注意QV 的长度相同)。

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

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

为了鼓励使用现代编译器,启用 Fortran 2003 合规性,这与

R = PACK((/(i,i=1,5)/), Q.le.5.and.V.ne.1)

(带有适当的其他声明等)

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

【讨论】:

    猜你喜欢
    • 2019-09-07
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2011-09-13
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    相关资源
    最近更新 更多