n вложенные циклы for в fortran90

Я читал некоторые темы по этому поводу, но я не совсем думаю, что это отвечает на мой вопрос. если это так, то, пожалуйста, направьте меня в правильную тему, и я обязательно посмотрю снова.

вот моя проблема:

я хочу написать цикл 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'?


person drjrm3    schedule 18.02.2012    source источник
comment
я знаю об этом. об этом позаботятся простые функции allocate() и deletelocate().   -  person drjrm3    schedule 19.02.2012


Ответы (2)


если вы записываете индексы, у вас есть n-значное число в базе n (почти - есть смещение 1, потому что вы используете индексы на основе 1 в фортране). и то, что вы просите, - это все возможные значения, которые может принимать это число.

другими словами, если мы для простоты на мгновение воспользуемся индексами, отсчитываемыми от 0, у вас будет:

  • n=2, значения=00,01,10,11 (двоичный счет от 0 до 3)
  • n=3, значения=000,001,002,010,011,012,020,021,022, 100,101,102,110,111,112,120,121,122, 200,201,202,210,211,212,220,221,222 (троичный(?) счет26)

так что вы спрашиваете, как это сделать в общем случае.

и вы можете сделать это, используя массив для хранения n цифр, начиная с [0,0....0]. затем в цикле while (который заменит ваши n вложенных циклов for) попробуйте увеличить самую правую запись (цифру). если это равно n, то вернуться к нулю и увеличить влево. как только вам удастся увеличить значение, не достигнув n, вы «готовы» и можете использовать числа в качестве своих индексов.

это довольно просто - вы просто добавляете 1 каждый раз.

затем, для индексации Фортрана на основе 1, добавьте 1 к каждой цифре. другими словами, измените приведенное выше, чтобы начать с 1 и двигаться влево на n + 1.

например, для n=4:

  • start with [1,1,1,1]
    • do your inner loop action
  • increment rightmost to [1,1,1,2]
    • do your inner loop action
  • increment rightmost to [1,1,1,3]
    • do your inner loop action
  • increment rightmost to [1,1,1,4]
    • do your inner loop action
  • увеличить крайний правый до [1,1,1,5]
  • the digit you incremented is now at n+1, which means back to 1 and increment digit to left [1,1,2,1]
    • do your inner loop action
  • increment rightmost to [1,1,2,2]
    • do your inner loop action
  • и т.д..
person andrew cooke    schedule 18.02.2012

Я думаю, вы могли бы сделать это, только свернув циклы в один цикл 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
person haraldkl    schedule 18.02.2012