Recursion 如何制作内部使用循环变量的递归嵌套循环?
我需要制作一个任意深度的嵌套循环。递归循环似乎是正确的方法,但我不知道如何在循环中使用循环变量。例如,一旦我将深度指定为3,它应该像Recursion 如何制作内部使用循环变量的递归嵌套循环?,recursion,fortran,nested-loops,Recursion,Fortran,Nested Loops,我需要制作一个任意深度的嵌套循环。递归循环似乎是正确的方法,但我不知道如何在循环中使用循环变量。例如,一旦我将深度指定为3,它应该像 count = 1 for i=1, Nmax-2 for j=i+1, Nmax-1 for k=j+1,Nmax function(i,j,k,0,0,0,0....) // a function having Nmax arguments count += 1 end
count = 1
for i=1, Nmax-2
for j=i+1, Nmax-1
for k=j+1,Nmax
function(i,j,k,0,0,0,0....) // a function having Nmax arguments
count += 1
end
end
end
我想做一个子程序,把循环的深度作为参数
更新:
我实施了佐尔坦提出的方案。为了简单起见,我用python编写了它
count = 0;
def f(CurrentDepth, ArgSoFar, MaxDepth, Nmax):
global count;
if CurrentDepth > MaxDepth:
count += 1;
print count, ArgSoFar;
else:
if CurrentDepth == 1:
for i in range(1, Nmax + 2 - MaxDepth):
NewArgs = ArgSoFar;
NewArgs[1-1] = i;
f(2, NewArgs, MaxDepth, Nmax);
else:
for i in range(ArgSoFar[CurrentDepth-1-1] + 1, Nmax + CurrentDepth - MaxDepth +1):
NewArgs = ArgSoFar;
NewArgs[CurrentDepth-1] = i;
f(CurrentDepth + 1, NewArgs, MaxDepth, Nmax);
f(1,[0,0,0,0,0],3,5)
结果是
1 [1, 2, 3, 0, 0]
2 [1, 2, 4, 0, 0]
3 [1, 2, 5, 0, 0]
4 [1, 3, 4, 0, 0]
5 [1, 3, 5, 0, 0]
6 [1, 4, 5, 0, 0]
7 [2, 3, 4, 0, 0]
8 [2, 3, 5, 0, 0]
9 [2, 4, 5, 0, 0]
10 [3, 4, 5, 0, 0]
也许有更好的方法可以做到这一点,但到目前为止,这一种效果很好。用fortran做这件事似乎很容易。非常感谢你的帮助 从面向对象的方法来看,每个循环都可以由一个“循环”对象表示——这个对象可以在包含自身的另一个实例的同时进行构造。从理论上讲,你可以把它们埋得尽可能深
Loop1将执行Loop2将执行Loop3。。您可以将函数定义为具有一个
列表
参数,该参数最初为空
void f(int num,List argumentsSoFar){
// call f() for num+1..Nmax
for(i = num+1 ; i < Nmax ; i++){
List newArgs=argumentsSoFar.clone();
newArgs.add(i);
f(i,newArgs);
}
if (num+1==Nmax){
// do the work with your argument list...i think you wanted to arrive here ;)
}
}
void f(int num,List arguments至今){
//为num+1..Nmax调用f()
对于(i=num+1;i
警告:堆栈应该能够处理
Nmax
depth函数调用这里有一种方法可以让您随心所欲。这是伪代码,我还没有编写足够的代码来编译和测试它,但您应该了解情况
定义一个函数,我们将其称为fun1
,除其他外,它接受一个整数数组参数,可能如下所示
<type> function fun1(indices, other_arguments)
integer, dimension(:), intent(in) :: indices
...
fun1([4,5,6],...)
对这一点的解释是,函数是使用一个3层深的循环嵌套,如下所示:
do ix = 1,4
do jx = 1,5
do kx = 1,6
...
当然,您不能编写深度在运行时确定的循环嵌套(无论如何不能在Fortran中),因此您可以将其展平为沿着
do ix = 1, product(indices)
如果需要循环中各个索引的值,则需要取消线性化索引的平台。请注意,您所做的只是编写代码,将数组索引从N-D转换为1-D,反之亦然;当您可以在编译时指定数组的秩时,编译器会为您执行此操作。如果内部循环不在整个索引范围内运行,您将不得不执行更复杂的操作,需要仔细编码,但并不困难
这取决于你实际想做什么,可能是好的,也可能不是令人满意的方法。如果您试图编写一个函数来计算数组中每个元素的值,而在编写函数时数组的秩是未知的,那么前面的建议完全错误,在这种情况下,您可能需要编写一个
elemental
函数。如果您想了解更多信息,请更新您的问题。另一种实现您愿望的方法是基于“高性能分数”的答案,但可以更一般化:
subroutine nestedLoop(indicesIn)
! Input indices, of arbitrary rank
integer,dimension(:),intent(in) :: indicesIn
! Internal indices, here set to length 5 for brevity, but set as many as you'd like
integer,dimension(5) :: indices = 0
integer :: i1,i2,i3,i4,i5
indices(1:size(indicesIn)) = indicesIn
do i1 = 0,indices(1)
do i2 = 0,indices(2)
do i3 = 0,indices(3)
do i4 = 0,indices(4)
do i5 = 0,indices(5)
! Do calculations here:
! myFunc(i1,i2,i3,i4,i5)
enddo
enddo
enddo
enddo
enddo
endsubroutine nestedLoop
现在已经显式编码了嵌套循环,但除非另有要求,否则这些都是单程循环。请注意,如果您打算构造取决于嵌套循环深度的秩数组,则可以将秩增加到7,如果您有支持它的编译器(Fortran 2008),则可以将秩增加到15。您现在可以尝试:
call nestedLoop([1])
call nestedLoop([2,3])
call nestedLoop([1,2,3,2,1])
您可以根据自己的喜好和所需的适用性修改此例程,添加异常处理等。您可以标记语言吗?可以用C++模板来解救。对于Java,您可能应该使用一个列表&c、 附言。我用的是fortran90。谢谢你,佐尔坦!我需要更多的时间来用fortran的方式思考这个例程。很抱歉,我没有把语言标签…谢谢你的解决方案。很高兴知道总是有各种各样的方法来做同样的事情!谢谢你的代码,并指出了一个我没有考虑的限制。我很好奇,即使递归循环也被限制在7次还是15次。对不起,我太傻了。最大秩限制实际上仅适用于数组。我现在看到,您打算调用具有一定数量参数的函数或子例程,因此最大秩限制不适用于此。我将相应地编辑我的答案。