파일을 읽어서 해당범위에 해당하는 갯수를 카운트 해야하는데 갯수가 계속 0이 나옵니다...
이유를 알려주시면 감사하겠습니다!
Program Exercise
Implicit none
Integer,Parameter :: it=40,ih=18
Real,dimension(:),allocatable :: hs,tp
Real :: del=0.5,head1(it),head2(it),hh,tt,h1,h2
Integer :: yy,mm,dd,hr,bb,i,j,ic,ndata,ihn,itn,table(ih,it),
& hsum,tsum,m
! ih, it = 파고 및 주기 범위 갯수
! del = 파고 및 주기의 간격
! ic = ndata = 전체데이터갯수
! ihn, itn = 파고 및 주기의 범위 (번째)
! table(ih,it) = 특정칸에 해당되는 자료의 갯수
! ptable(ih,it) = 확률
Open(1,file='TS_1979-2022_106-2.dat',status='old')
Open(2,file='Exercise_result.dat',status='unknown')
ic = 0 ! 전체 데이터 갯수
11 Continue
Read(1,*,end=999) yy, mm, dd, hr, bb, hh, tt
ic = ic + 1
hs(ic) = hh ; tp(ic) = tt
Go to 11
999 Continue
ndata = ic
allocate(hs(ndata),tp(ndata))
table = 0.0 ! table 초기화
Do i = 1,ndata ! ihn, itn 범위 설정
ihn = int(hs(i)/del)+1
itn = int(tp(i)/del)+1
End do
Do i = 1, ih ! 가로(행)합
hsum = 0
Do j = 1, it
hsum = hsum + table(i,j)
End do
table(i,it) = hsum
End do
Do j = 1, it ! 세로(열)합
tsum = 0
Do i = 1, ih
tsum = tsum + table(i,j)
End do
table(ih,j) = tsum
End do
table(ih,it)= table(ih,it) + 1 ! table(ih,it) 하나씩 늘리기
Do i = 1, ih ! table(데이터 갯수) 계산
Do j= 1, it
table(i,it) = table(i,it) + table(i,j)
End do
End do
head1(1) = 0.0 ; head2(1) = 0.5
Do m = 1, it-1
head1(m+1) = head1(m) + del
head2(m+1) = head2(m) + del
End do
Write(2,13) (head1(i), i = 1, it)
13 Format(5x,'\ TP(s)|',40(2x,F4.1,2x),' | ')
write(2,14) (head2(i), i = 1, it)
14 Format('HS(m) \ |',40(3x,'~',F4.1),' | ',' Total ')
Write(2,"(380('='))")
Do i = 1, ih-1
h1 = ((ih-1)-i)*del
h2 = h1 + del
Write(2,15) h1, h2, (table(i,j), j = 1, it)
15 Format(F4.2,' - ', F4.2, ' | ', 40I8, ' | ')
End do
Write(2,"(380('='))")
deallocate(hs,tp)
End program
<제가 짠 코드>
<결과물>
table을 구하는 코드가 잘못된것같은데 어떻게 구하는걸까요...?
<읽어드린 파일 형식> : HS(파고)와 TMM10(주기)만 필요해서 여기까지만 읽었습니다
첫댓글 코드가 긴데 사진으로 올리면 봐주고 싶어도 '그걸 나보고 보면서 다 따라 쳐서 코드 봐주라고?' 라고 생각하게 될 거에요.
입력 자료도 마찬가지로 파일로 올리심이 좋을 듯 합니다.
코드 자료는 올렸는데 오픈파일은 너무 커서 안올라갑니다 ㅠ 385695줄까지 데이터가 있어서...
@민초냠냠 100줄만 올리셔도 충분하겠죠. 데이터 크기는 맞춰서 파일 끝 처리 하면 되니
@연필 넵 말씀하신부분들 좀 수정해봤는데 그래도 결과값은 0이 나오네요...ㅜㅜ
@민초냠냠 전녁에 봐드릴 수 있을 듯해요. 그전에 성공하시길 ㅎ
@연필 네 열심히 수정해보겠습니다....!!
일단 쓱봐서 눈에 거슬리는 첫번째는 GO TO 문이고, DO문으로 바꾸는 것 추천
처음에 Do문으로 작성했다가 자료 크기를 왜 알거라고 생각하냐는 피드백을 받아서 자료 갯수 다 세려고 저렇게 코드 짰습니다
팁들...
초기화 같은 곳에서 개별 배열 원소별 접근하기 위해 Do를 쓰기 보다 그냥 배열명을 쓰시면 편합니다.
합을 구하는 식 같은 것도, 배열의 부분식을 활용하면 Do없이도 구해집니다.
ifix 같은 것도 그냥 int를 사용하는 편이 보기 편하고 나중에 사용성이 더 좋아지기도 합니다.
+ (이러한 것을 일반명 접근이라고 합니다. Generic)
table(ih,it) = 0 -> 이렇게 해도 초기화가 된다는 말일까요?
@민초냠냠 table = 0.0
@민초냠냠 배열명을 이용한 접근, 배열 부분식등을 잘 이해하고 활용하는 것 등등이 나아중에 혹시 관심있을 최적화와 병렬화에도 도움이됩니다.
컴파일러는 꽤 똑똑해서 잘 최적화 해주긴 합니다만.
좀 단편적으로 이야기하자면 ( 실제와는 다르지만 편협하게 설명하면)
컴파일러가 Do를 만나서 도중 무슨 일이 일어날 지 모르니 일단 한땀한땀 처리 하는거랑, 프로그래머가 '여기서 ~ 여기까지 한통으로 처리해버려' 라고 말해주는 거랑 다르죠.
@민초냠냠 코드 다시 보니 정수네요. 0.0대신 0이 바람직하네요
데이터의 갯수만크만 읽어서 배열의 크기를 결정하는 것이 좋겠지만,
allocate를 아직 잘 사용하지 못하겠 면, ll의 크기도 적당히 작게 시작하는 것이 좋을 듯합니다. 어짜피 옆에 상수로 크기가 있는데 굳이 클 필요 없잖아요.
allocate를 쓰면 데이터의 갯수만큼만 배열의 크기가 정해지는 거였나요? 인터넷에서 allocate 쓴 예시 봐도 이해가 잘 안돼서 안썼는데...한번 써보겠습니다
입력자료가 csv라면 read문에서 포멧을 입력하는 것보다, *(애스터리스크)로 그냥 list directed로 받는 것도 좋습니다. 콤마로 구별되지 않아도 공백이라면 list directed 방식으론 같게 취급합니다.
주의점은 위의 예에서 맨앞에 날짜데이터처럼 '문자' 데이터를 다르게 한번 더 읽어주는 번거로움도 있긴 하지만... 그렇다고요 ㅎ
read문에서의 포멧은 write에서의 포멧과 생각과는 살짝 다른면이 있을거에요.
사실 한 라인 전체를 문자열로 읽어버리고, 읽어들인 것을 다시 list-directed나 원하는 formatted로 읽는게 처리시 약간의 깔끔함을 얻기도 해요.
파일 입출력에 대한 것은 샘플이 될만하게 답글로 작성해드려요. 빼고 더하고 해서 응용은 잘 해보세요. 다른 데이터 처리할 때에도 비슷하게 많이 쓰실 수 있을거에요.
코드에서 ih와 it 는 상수이므로, 해당하는 것들을 코드상에서도 40, 18로 바꾸어 확인 해보셔요.
그런 이유로 위와 같은 코드는 왜 있는지 모르겠어요. 58라인
table(ih, it) = table(ih, it) + 1
summation을 하려면
sum 함수를 쓰는게 Do문을 쓰는 것보다 편하실 거에요.
hsum, tsum 같은걸로 뭘 하려하는지 모르겠으니 0으로 초기화 하는 위치가 저기가 맞나? 싶어서 모르겠네요.
35~ 38 라인도 좌변이 스칼라인데, Do문을 반복하면 맨 마지막 계산만 유효계산이 되겠죠?