如何退出嵌套的Fortran循环?

时间:2017-10-08 15:05:36

标签: fortran

我试图编写一个程序(在Fortran 95中),找到自然数最多为N的最小分解为最多4个正整数的总和。

我一直试图添加和删除语句一段时间,以使其仅停留在最小分解但我没有到达任何地方。如何在程序发现最小分解后立即停止程序?

PROGRAM SummeQuadrat
IMPLICIT NONE
 real:: start,finish
 integer:: a,b,c,d,g,x,y

 write(*,*) "Max n"
 read (*,*) y
 call cpu_time(start)

do x=1,y,1

  do a=0,x,1
   do b=a,x-a,1
    do c=b,x-b,1 
     do d=c,x-c,1
      if (a**2+b**2+c**2+d**2 .eq. x) then 
      write(*,*) "x=",x,d,c,b,a

      end if
     end do 

    end do
   end do
  end do
end do
call cpu_time(finish)
    write(*,*)finish-start
 end program SummeQuadrat

2 个答案:

答案 0 :(得分:1)

正如我在评论中所解释的那样,我不确定你是只是要问如何摆脱循环或更多。

您可以使用EXIT语句跳出任何循环。要退出不是当前最内层循环的循环,请使用带标签的循环并使用EXIT语句中的标签退出该特定循环。

outer: do x = 1, y

  do a = 0, x
   do b = a, x-a
    do c = b, x-b
     do d = c, x-c
      if (a**2+b**2+c**2+d**2 == x) then 
        write(*,*) "x=",x,d,c,b,a
        if (minimal(a,b,c,d)) exit outer
      end if
     end do 

    end do
   end do
  end do
end do outer

答案 1 :(得分:0)

旧帖子,但这是一个有趣的问题,所以我想我可能会发表自己的解释。

首先,如果我们稍微欺骗并查看the solution,可以看出只有当x = 4 ** k *(8 * m + 7)时才需要所有4个方格。因此,我们可以廉价地搜索1或2平方解,并且在失败时根据上述标准决定是否搜索3或4平方解。

然后,当我们构造我们的循环时,从最大的a倒计数使得a ** 2 <= x,然后最大的b <= a使得a ** 2 + b ** 2 <= x等等。这会将问题从O(x ** 4)降低到O(x ** 1.5),因此可以更快地完成。

对于输出格式,通过明​​智地使用冒号格式,我们可以编写一种格式,以更可读的方式打印出结果。

! squares.f90 -- Prints out minimal decomposition x into squares
!                for 1 <= x <= y (user input)
program squares
   use ISO_FORTRAN_ENV, only: REAL64
   implicit none
! Need this constant so we can take the square root of an
! integer.
   real(REAL64), parameter :: half = 0.5_REAL64
   real start, finish
   integer a,b,c
   integer amax,bmax,cmax,dmax
   integer amin,bmin,cmin
   integer x,y
! Format for printing out decomposition into squares
   character(40) :: fmt = '(i0," = ",i0"**2":3(" + ",i0,"**2":))'
   integer nzero

! Get uper bound from user
   write(*,'(a)',advance='no') 'Please enter the max N:> '
   read(*,*) y
   call cpu_time(start)
! Loop over requested range
   outer: do x = 1, y
      amax = sqrt(x+half)
! Check for perfect square
      if(amax**2 == x) then
         write(*,fmt) x,amax
         cycle outer
      end if
! Check for sum of 2 squares
      amin = sqrt(x/2+half)
      try2: do a = amax, amin, -1
         bmax = sqrt(x-a**2+half)
         if(bmax > a) exit try2
         if(a**2+bmax**2 == x) then
            write(*,fmt) x,a,bmax
            cycle outer
         end if
      end do try2
! If trailz(x) is even, then x = 4**k*z, where z is odd
! If further z = 8*m+7, then 4 squares are required, otherwise
! only 3 should suffice.
      nzero = trailz(x)
      if(iand(nzero,1)==0 .AND. ibits(x,nzero,3)==7) then
         amin = sqrt(x/4+half)
         do a = amax, amin, -1
            bmax = sqrt(x-a**2+half)
            bmin = sqrt((x-a**2)/3+half)
            do b = min(bmax,a), bmin, -1
               cmax = sqrt(x-a**2-b**2+half)
               cmin = sqrt((x-a**2-b**2)/2+half)
               do c = min(cmax,b), cmin, -1
                  dmax = sqrt(x-a**2-b**2-c**2+half)
                  if(a**2+b**2+c**2+dmax**2 == x) then
                     write(*,fmt) x,a,b,c,dmax
                     cycle outer
                  end if
               end do
            end do
         end do
      else
         amin = sqrt(x/3+half)
         do a = amax, amin, -1
            bmax = sqrt(x-a**2+half)
            bmin = sqrt((x-a**2)/2+half)
            do b = min(bmax,a), bmin, -1
               cmax = sqrt(x-a**2-b**2+half)
               if(a**2+b**2+cmax**2 == x) then
                  write(*,fmt) x,a,b,cmax
                  cycle outer
               end if
            end do
         end do
      end if
! We should have a solution by now. If not, print out
! an error message and abort.
      write(*,'(*(g0))') 'Failure at x = ',x
      stop
   end do outer
   call cpu_time(finish)
   write(*,'(*(g0))') 'CPU time = ',finish-start
end program squares
相关问题