我已经阅读了一些有关此的主题,但我不太认为它回答了我的问题。如果确实如此,请引导我到正确的主题,我一定会再看一次。
这是我的问题:
我想编写一个 for 循环,它将循环遍历数组长度为“n”的每个可能的组合。
也就是说,如果 n = 2 那么我的 for 循环将是
do i1 = 1,2
do i2 = 1,2
! do stuff here
enddo
enddo
如果 n = 3 那么我的数组看起来像
do i1 = 1,3
do i2 = 1,3
do i3 = 1,3
! do stuff here
enddo
enddo
enddo
等等。我将如何编写一个例程,只需输入变量“n”即可自动执行此操作?
如果你写出索引,你得到的是一个以 n 为基数的 n 位数字(几乎 - 偏移量为 1,因为你在 fortran 中使用基于 1 的索引)。 你要求的是该数字可以取的每个可能值。
换句话说,如果我们为了简单起见暂时使用基于 0 的索引,您将得到:
所以你要问的是在一般情况下如何做到这一点。
您可以使用数组来保存从 [0,0....0] 开始的 n 位数字。 然后,在“while”循环中(它将替换您的n个嵌套for循环),尝试增加最右边的条目(数字)。 如果等于 n,则返回到零并向左递增。 一旦您设法在不达到 n 的情况下增加一个值,那么您就“完成”了,可以使用这些数字作为索引。
非常简单 - 每次只需加 1。
然后,对于 fortran 基于 1 的索引,每个数字加 1。 换句话说,将上面的内容更改为从 1s 开始,并在 n+1 处向左移动。
例如,对于 n=4:
我猜你只能通过将循环折叠成一个 n**n 循环来做到这一点,并从折叠的全局索引中计算单独的 n 索引(或者简单地用不同的步幅对它们进行计数)。
编辑:尝试将其放入示例代码中:
do i=1,n**n
do j=1,n
ind(j) = mod((i-1)/max((j-1)*n,1),n) + 1
end do
! Some code using ind(1:n)
end do
考虑以下形式的一般 n 层嵌套 do 循环:
DO IX(1) = 1, NX(1)
DO IX(2) = 1, NX(2)
.....
DO IX(N) = 1, NX(N)
perform operations on F(IX(1),IX(2), ..., IX(N))
ENDDO
.....
ENDDO
ENDDO
等效的单循环构造如下:
NT = NX(1)
DO I = 2, N
NT = NT * NX(I)
ENDDO
DO K=1,NT
M = K
DO I = N,1,-1
NN = 1
DO J = 1, I - 1
NN = NN * NX(J)
ENDDO
IF (I .GT. 1) THEN
IX(I) = (M-1) / NN + 1
M = M - (IX(I) - 1) * NN
ELSE
IX(I) = M
ENDIF
ENDDO
perform operations on F(IX(1),IX(2), ..., IX(N))
ENDDO