我需要一個通用的 fortran 程式來獲取r元素串列中所有可能的元素組合n。我發現這段代碼可以列印所有組合(r=3,n =5),但我需要將它們存盤在一個陣列中。
我試圖將它們記錄為write陳述句附近的行,但它不起作用。將遞回子程式變成遞回函式也是行不通的。
program combinations
implicit none
integer, parameter :: m_max = 3
integer, parameter :: n_max = 5
integer, dimension (m_max) :: comb
character (*), parameter :: fmt = '(i0' // repeat (', 1x, i0', m_max - 1) // ')'
call gen (1)
contains
recursive subroutine gen (m)
implicit none
integer, intent (in) :: m
integer :: n
if (m > m_max) then
write (*, fmt) comb
else
do n = 1, n_max
if ((m == 1) .or. (n > comb (m - 1))) then
comb (m) = n
call gen (m 1)
end if
end do
end if
end subroutine gen
end program combinations
uj5u.com熱心網友回復:
首先,混合全域變數和遞回程序是一種很好的方法,會引起很多不必要的混淆和除錯,所以讓我們把combandn_max變成程序引數,使用size(comb)to give m_max,現在替換fmt為*:
program combinations
implicit none
integer :: comb(3)
call gen(comb, 1, 5)
contains
recursive subroutine gen(comb, m, n_max)
integer, intent(inout) :: comb(:)
integer, intent(in) :: m
integer, intent(in) :: n_max
integer :: n
if (m > size(comb)) then
write (*, *) comb
else
do n = 1, n_max
if ((m == 1) .or. (n > comb(m - 1))) then
comb(m) = n
call gen(comb, m 1, n_max)
end if
end do
end if
end subroutine gen
end program combinations
接下來要注意的是您的代碼中有一個微妙的錯誤。線
if ((m == 1) .or. (n > comb (m - 1))) then
不保證如果m=1. Fortran不保證邏輯運算子 的短路,因此即使(m == 1)評估為.true.,(n > comb (m - 1))也可能會評估 ,從而導致段錯誤。讓我們通過引入一個變數來解決這個問題n_min,并正確計算它:
recursive subroutine gen(comb, m, n_max)
integer, intent(inout) :: comb(:)
integer, intent(in) :: m
integer, intent(in) :: n_max
integer :: n
integer :: n_min
if (m > size(comb)) then
write (*, *) comb
else
if (m == 1) then
n_min = 1
else
n_min = comb(m-1) 1
endif
do n = n_min, n_max
comb(m) = n
call gen (comb, m 1, n_max)
end do
end if
end subroutine gen
好的,現在我們可以開始考慮從gen. 為此,讓我們gen從 a更改subroutine為 a function,并讓它回傳一個二維陣列。我們需要將一個二維陣列附加到另??一個陣列上,所以現在讓我們撰寫一個函式來執行此操作:
function append_combinations(input, new_combinations) result(output)
integer, intent(in) :: input(:,:)
integer, intent(in) :: new_combinations(:,:)
integer, allocatable :: output(:,:)
allocate(output(size(input,1), size(input,2) size(new_combinations,2)))
output(:, :size(input,2)) = input
output(:, size(input,2) 1:) = new_combinations
end function
現在整個程式看起來像
program combinations
implicit none
integer :: comb(3)
integer, allocatable :: combs(:,:)
integer :: i
combs = gen(comb, 1, 5)
write(*, *) ""
do i=1,size(combs,2)
write(*, *) combs(:,i)
enddo
contains
recursive function gen(comb, m, n_max) result(combs)
integer, intent(inout) :: comb(:)
integer, intent(in) :: m
integer, intent(in) :: n_max
integer, allocatable :: combs(:,:)
integer :: n
integer :: n_min
integer, allocatable :: new_combs(:,:)
if (m > size(comb)) then
write (*, *) comb
combs = reshape(comb, [size(comb),1])
else
if (m == 1) then
n_min = 1
else
n_min = comb(m-1) 1
endif
allocate(combs(size(comb), 0))
do n = n_min, n_max
comb(m) = n
new_combs = gen(comb, m 1, n_max)
combs = append_combinations(combs, new_combs)
end do
end if
end function gen
function append_combinations(input, new_combinations) result(output)
integer, intent(in) :: input(:,:)
integer, intent(in) :: new_combinations(:,:)
integer, allocatable :: output(:,:)
allocate(output(size(input,1), size(input,2) size(new_combinations,2)))
output(:, :size(input,2)) = input
output(:, size(input,2) 1:) = new_combinations
end function
end program combinations
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/434921.html
