gpt4 book ai didi

arrays - 以向量下标作为过程参数的数组部分

转载 作者:行者123 更新时间:2023-12-05 01:25:28 26 4
gpt4 key购买 nike

这是我的问题的一个例子(在我的真实程序中,A 会更大且随机):

    MODULE MOD_TST
contains
subroutine function_tst(A,B)
real,intent(in) :: A(:)
real,intent(out) :: B(:)
integer :: i, n
n = size(A)
do i=1,n; B(i) = A(i); end do
end subroutine function_tst
end module MOD_TST

PROGRAM PROG_TST
USE MOD_TST

IMPLICIT NONE
integer,allocatable :: A(:),B1(:),B2(:),subA(:),subB(:)
integer :: i, n = 10, p = 3
integer,allocatable :: list(:)

allocate(A(n),B1(n),B2(n))
A = (/ 9, 5, 4, 7, 8, 1, 6, 0, 3, 2/)

list = pack ( [( i, i=1,n )] , modulo(A,p) .eq. 0)
allocate(subA(size(list)),subB(size(list)))
subA=A(list); subB=B1(list);

call function_tst(subA,subB)
B1(list) = subB

call function_tst(A(list),B2(list))

write(*,*)'A ',A
write(*,*)'B1',B1
write(*,*)'B2',B2
END PROGRAM PROG_TST

我得到的输出是:

A 9 5 4 7 8 1 6 0 3 2

B1 9 0 0 0 0 0 6 0 3 0

B2 0 0 0 0 0 0 0 0 0 0

有没有办法让它工作而不必为过程创建中间变量?

最佳答案

带有矢量下标的数组部分在使用方式上受到非常严格的限制。作为一般(主观)规则,可以公平地说,如果可能的话,应该避免使用它们。在进入细节之前,什么是带有向量下标的数组部分?

一个向量下标是一个整型数组或秩为1,有这样一个下标的数组部分就是整体的元素被这个下标数组选中的部分:

integer :: i(5)=[1,2,3,4,5]
print *, i([1,2,5])

每当使用这种形式时,数组部分都有一个向量下标,无论它是否包含整个数组的所有元素,是一个连续的子数组,还是多次选择一个元素。

在最高级别上,当向量数组多次指定同一元素时,带有向量下标的数组会受到特别限制:这样的数组部分永远不会受到“定义”的约束:

integer i(5)
i([1,3,2]) = [1,2,3] ! Allowed
i([1,3,1]) = [1,2,3] ! Not allowed

因此,在许多情况下,可以在子程序 function_tst 中看到的赋值可以直接对数组部分进行。

但是,在将这样的数组部分传递给过程的情况下,虚拟数组是 never1 definable ,即使没有重复或者数组部分是整个数组的连续部分。这意味着,在问题的情况下

call function_tst(A(list),B2(list))

绝不允许。

另请注意,带有矢量下标的数组部分受到限制,以避免容易“黑客攻击”:

  • 带有向量下标的数组部分不能是指针的目标
  • 与带有矢量下标的数组部分关联的关联名称永远不可定义

解决此问题的一种方法是创建一个临时副本并将更改传回原始副本。这很笼统,即使写起来很痛苦。但是,并不能保证所有程序都是安全的:

Btemp = B(list) ! If the argument is for an intent(inout), skip if inient(out)
call other_subroutine(A(list), Btemp)
B(list) = BTemp ! Can be dangerous

具体到具体例子中的action类型是一个elementary procedure。正如我们可以写的那样

B2(list) = A(list)  ! No repeats in list

我们可以

call function_tst(A(list),B(list)) 

如果我们让那个子程序成为元素

elemental subroutine function_tst(A,B)
integer, intent(in) :: A
integer, intent(out) :: B
B=A
end subroutine function_tst

如果子例程适合作为元素,那么您还可以选择遍历索引数组:

do i=1, size(list)
call function_tst(A(list(i):list(i)), B(list(i):list(i)))
end do

这些仅适用于元素之间完全独立的情况。

介于这些极端之间的是重写为函数(如 veryreverie's answer 所示)。使用函数,您还可以考虑屏蔽赋值,例如使用 WHERE 语句和构造。

与简单的赋值事件一样,基本的或循环的子例程或函数,或掩码赋值不会通用到涵盖所有需求。每个备选方案都有其自身潜在的缺陷或缺点。重复一遍:矢量下标受到高度限制。然而,它们通常可以避免。


1 有两个异常(exception):一个继续阅读;第二个是 VALUE 属性(在这种情况下没有帮助)。

关于arrays - 以向量下标作为过程参数的数组部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70809410/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com