2011-09-08 26 views
1

시뮬레이션을 수행하는 포트란 코드가 있습니다. 경과 시간은 et에 저장되고 시간 단계는 dt에 저장됩니다. 둘 다 실제 유형으로 정의됩니다. 시뮬레이션을 실행해야하는 최대 시간을 보유하는 다른 실제 변수 tot이 있습니다. i은 정수 유형의 계수 변수입니다. 내 첫 번째 시도는 다음과 같이이었다 : 나는이 시도 할 때 총 시간이 클 때 그것이 단지 한 곳에서 사용 된 이후 i 제거하고 싶어Fortran으로 루프 내부에서 계산하기

real, intent(in) :: dt 
real, intent(in) :: tot 

real :: et 
integer :: i 

et = 0.0 
i = 0 
do 
    i = i+1 
    et = real(i)*dt 
    if (et > tot) exit 

    ! main code here 
end do 

그러나, 프로그램은 중단 :

real, intent(in) :: dt 
real, intent(in) :: tot 

real :: et 

et = 0.0 
do 
    et = et + dt 
    if (et > tot) exit 

    ! main code here 
end do 

두 가지 코드 샘플의 차이점은 프로그램이 너무 다르게 반응하게합니까? 제 컴파일러는 g77입니다.

편집 : 위의 코드 샘플에 선언 및 초기화를 추가했습니다.

편집 2 : 서브 루틴에 전달 된 초기 값은 dt = 1e-6

+0

어떻게 프로그램이 멈 춥니 까? 오류? 무한 루프 (예 : 'et'가 'tot'에 도달하지 않음)? –

+0

@ 앤더스 : 프로그램이 멈추지 않고 10 분 이상 실행되기 때문에 무한 루프를 가정합니다 (코드의 첫 번째 버전을 사용하면 약 1.5 분 후에 중단됩니다). – astay13

+0

'et'는 메인 코드의 어딘가에서 다시 정의 된 것 같습니다. 값을 인쇄하여 예상대로 작동하는지 확인 했습니까? –

답변

4

DT는 TOT와 관련하여 매우 작은 경우 을 기록 할 수있는 두 가지 방법이 있습니다, 그 다음에는 크고, et에 아무런 영향도주지 않으므로 (숫자 정밀도에서 손실 됨) et는 그 점을 넘어서서 성장하지 않습니다 ...

+0

그냥'et = et + dt' 1e8 번하고,'et'는 32.0이고 그 이상으로 32.0을 유지합니다. – steabert

+0

귀하의 도움에 감사드립니다! – astay13

5

난 당신이 전체 프로그램을 제공하지 않기 때문에이이 오류가 있는지 알고,하지만 첫 번째 코드의 첫 번째없는 tot = 100. 있습니다 당신이하는 일은 etdt과 같으므로 그 시점에서 i=1이됩니다. 그러나 두 번째 코드에서는 et을 설정하지 않고 (우리가 추측 할 수있는 한) 사용하고 있습니다. 또한 dt은 초기화되지 않은 것으로 보입니다. et의 메모리 주소에있는 바이트가 큰 음의 float을 발생시키는 경우 tot에 도달하는 데 훨씬 오래 걸릴 수 있습니다. 그것은 더 많은 코드가 없어도 무엇이든 생각할 수있는 한도 내입니다.

EDIT 감사합니다.

글쎄, 내가 방금 하 할드 켈의 대답을 읽은 것 같아, 그게 해결책이라고 생각해. 1.0e-6을 추가하여 100에 도달해야하는 경우 4 기수 실제의 경우에는 작동하지 않습니다. 기본 10 자리의 의미있는 자릿수가 약 6 ~ 7 자이기 때문에 첫 번째 해결 방법은 매우 적합합니다. 약 2e9와 4 바이트 int. 한 가지 해결책은 8 바이트 변수를 사용하는 것입니다. 그러나 최대 반복을 허용하기 위해 항상 여분의 체크 (예 : if (et > tot .OR. i > max_iter))를 작성해야합니다. 따라서 정수 솔루션을 사용하더라도 tot을 더 크게 만들면 정수가 오버플로가 발생하면 무한 루프에 빠지게됩니다.

+0

위의 편집을 참조하십시오. 미안 원래 질문에 초기화를 포함하지 않았습니다. – astay13

0

부분 코드를 입력 할 때 선언을 건너 뛰고 오류 메시지를 표시하는 대신 오류를 올바르게 해석하는 방법을 알고 있다면 오류 메시지를 표시하는 것이 좋습니다. 처음부터 그들을 데려오고있어.

두 번째 루프는 주목할 가치가있는 몇 가지 점에서 첫 번째 루프와 다릅니다. a) 루프 시작 부분의 변수 값은 무엇입니까? b) 루프 카운터는 무엇입니까? c) 실제 또는 정수입니까? ... 등등

여기 그것은 또한 하나 개의 포인트 DT에서이 너무 작은 수 있습니다, 이러한 루프

program various_do_loops 
    integer :: i 
    real :: et, tot, dt 


    ! DO WHILE LOOP (whoops, I just now see you're using g77 
    ! so this may or may not work) 
    i = 0 
    et = 0. 
    tot = 10. 
    dt = 1. 
    do while (et<tot) 
     i = i+1 
     et = real(i)*dt 
    ! main code goes here 
    ! .... 
    ! .... 
    write(*,'("et is currently ", f5.2)')et 
    end do 

    ! Old kind of WHILE LOOP 
    i = 0 
    et = 0. 
    tot = 10. 
    dt = 1. 
    10 if(et<tot) then 
     i = i + 1 
     et = real(i)*dt 
    ! main code goes here 
    ! .... 
    ! .... 
    write(*,'("et is currently ", f5.2)')et 
    goto 10 
    end if 

    end program various_do_loops 
+0

초기화/선언에 대한 위의 편집을 참조하십시오. 전체 코드는 충분히 커서 게시 할 수 없습니다. 오류 메시지가 없으므로 루프 카운팅 전략을 사용하여 프로그램이 상당히 오래 실행되고 이것이 왜 발생했는지 알고 싶다는 사실을 알게됩니다. – astay13

관련 문제