수리수리연수리 코드얍

3. Fortran의 변수 체계(실전편) 본문

즐거운 Fortran

3. Fortran의 변수 체계(실전편)

ydduri 2023. 2. 1. 10:10

실습 코드: ydduri 깃허브 - Joyful_Fortran_Tutorial

목차

1. Implicit Rules
2. 실수형 vs 배정도형
3. 문자형
4. 복소수형
5. 논리형
6. Parameter문

1. Implicit Rules

1) 변수 선언을 하지 않았을 때 기본 Implicit Rules(3_1_1.f90)

전전글인 3. Fortran의 변수 체계(이론편)에서 Fortran에 존재하는 변수 선언에 대한 묵시적인 규칙(Implicit Rules)에 대해서 배웠다. 이는 선언부에서 변수의 자료형을 선언하지 않았을 때, 변수 이름이 특정 영문자로 시작하면 '정수형', 그 외에는 '실수형'으로 자동 인식하는 기능이었다.

  • 변수 이름이 I, J, K, L, M, N으로 시작: 정수형
  • 그 외: 실수형

첫 번째로, 변수 선언을 하지 않았을 때 위와 같은 기본 Implicit Rules가 적용되는 모습을 확인해보자.

결과

   1.23000002               1           1
  • xvar: 변수명이 i, j, k, l, m, n 외의 영문자로 시작하므로 실수형으로 출력(실수형의 경우 전전글의 변수의 종류에 따른 기억장소 크기에서 설명했듯이 4바이트 크기, 자리수로는 5~10자리 정도의 크기를 가지기 때문에 1.23이라는 값을 할당했더라도 남은 공간이 저런 식으로 채워진다).
  • ivar: 변수명이 i로 시작하므로 정수형으로 출력
  • mvar: 변수명이 m으로 시작하므로 정수형으로 출력

* Fortran에서는 print* 이렇게 print 뒤에 별(*)을 붙여야 하나? 라는 생각이 드실 수 있는데, 이에 대해서는 4강에서 다룰 예정이니 해당 시리즈를 예의주시해주시면 좋을 것 같다!

2) Implicit문을 이용해 기본 Implicit Rules 바꾸기(3_1_2.f90)

위의 경우는 기본 Implicit Rules를 변형 없이 그대로 사용한 케이스에 해당한다. 두 번째로, 이번에는 Implicit문을 이용해 기본 Implicit Rules에 변형을 가해보자! i부터 n까지의 영문자로 시작하는 변수명은 실수로 인식하겠다는 implicit문을 작성했다. 이 경우 해당 범위의 영문자에 대해서는 우리가 설정한 implicit문 규칙이 우선 적용되고, 나머지 영문자에 대해서는 기본 implicit rules를 따른다.

결과

   1.23000002       1.23000002       1.23000002
  • xvar: 변수명이 i, j, k, l, m, n 외의 영문자로 시작하므로 기본 implicit rules에 따라 실수형으로 출력
  • ivar: 변수명이 i로 시작하므로 implicit문에 따라 실수형으로 출력
  • mvar: 변수명이 m으로 시작하므로 implicit문에 따라 실수형으로 출력

3) Implicit None(3_1_3.f90)

세 번째로, 해당 implicit문을 앞으로 우리가 계속 활용할 'implicit none'으로 수정하여 컴파일 해보자.

처음으로 에러가 떠서 놀라신 분들이 계실 것 같다. 그러나 이는 지극히 정상적인 결과다. implicit none을 썼다는 것은 implicit rules를 무시하고 모든 변수의 자료형을 직접 선언해주겠다는 뜻이다. 그런데 코드에서 사용한 변수인 xvar, ivar, mvar에 대한 자료형을 하나도 선언해주지 않았으므로 당연히 에러가 뜰 수밖에 없다.

앞으로 Fortran 코딩을 할 때는 선언부에서 implicit none을 반드시 써주고, 코드에서 사용한 모든 변수를 빠짐없이 선언해주어야 함에 유의하자.

2. 실수형 vs 배정도형

1) 실수형과 배정도형의 출력 결과 차이를 직접 확인해보자! 1탄(3_2_1.f90)

변수 a는 실수형, b는 배정도형으로 선언했다. 이때 a, b 모두에 1.2345678901234567이라는 매우 긴 소수를 넣었을 때 각각이 어떻게 출력되는지 확인해보자.

결과

   1.23456788       1.2345678806304932
  • a: 1.23456788(소수점 아래 7번째 자리까지 정확하게 출력)
  • b: 1.2345678806304932(소수점 아래 7번째 자리까지 정확하게 출력)

어라, 이게 무슨 일인가? 배정도형은 분명 배의 정밀도를 가져서 실수형에 비해 더 많은 자리수를 정확하게 출력한다고 했는데, 둘다 소수점 아래 7번째 자리까지만 정확하게 출력했다. 이는 변수 b를 배정도형으로 선언하긴 했으나, 막상 값을 할당할 때는 '실수형'으로 할당했기 때문에 그렇다.

Fortran은 1.2345678901234567 이렇게 일반적인 소수 형태는 아무리 길이가 길다 한들 '실수형'으로 인식한다. 배정도형 변수에 배정도형 값을 할당하고 싶다면 'd(혹은 D)'를 이용한 지수 표기법을 활용해야한다. 이 경우 1.2345678901234567d0 이런 식으로 나타내어야 Fortran이 배정도형으로 인식할 수 있다.

2) 실수형과 배정도형의 출력 결과 차이를 직접 확인해보자! 2탄(3_2_2.f90)

변수 a는 실수형, b는 배정도형으로 선언했다. 1탄에서 a, b 모두에 1.2345678901234567이라는 실수형 값을 넣어주었는데, 그렇다면 a, b 모두에 1.2345678901234567d0라는 배정도형 값을 할당하면 어떻게 될까? 직접 확인해보자.

결과

   1.23456788       1.2345678901234567
  • a: 1.23456788(소수점 아래 7번째 자리까지 정확하게 출력)
  • b: 1.2345678901234567(소수점 아래 16번째 자리까지 정확하게 출력)

정리를 하자면, 실수형으로 선언한 변수라면 애초에 그릇이 작기 때문에 배정도형 값을 할당하더라도 실수형으로 출력되지만, 배정도형으로 선언한 변수에 실수형 값을 할당하면 실수형 변수처럼 소수점 아래 5~10번째 자리 정도까지만 정확하게 출력하고 나머지는 이상한 값으로 채워져서 나온다. 그러니 되도록 실수형 변수에는 실수형 값을, 배정도형 변수에는 배정도형 값을 정확히 할당하도록 하자!

3. 문자형(3_3.f90)

char1과 char2를 길이 20짜리의 문자형 변수로 선언하고, char1에는 'Today is' 라는 문자열을, char2에는 'wednesday'라는 문자열을 할당했다. 코드를 보면 char1, char2 그 자체, char1, char2의 길이, char1, char2의 '공백을 제거'했을 때의 길이를 순서대로 출력하도록 되어 있다. 과연 어떤 결과가 나올까?

결과

 Today is            Wednesday.          
          20          20
           8          10

char1과 char2는 각각 'Today is'와 'Wednesday'가 잘 출력된 것으로 보인다. 그런데 정확히 말하면, 'Today is            ', 'Wednesday.          ' 이렇게 뒤에 공백이 붙어서 출력되었는데 육안으로 식별이 안 될 뿐이다.

앞서 char1, char2라는 문자형 변수를 선언하면서 길이를 20으로 지정했다. 그런데 Today is는 8글자(Fortran에서는 글자 사이에 있는 공백도 글자로 취급한다), Wednesday.는 9글자(Fortran에서는 마침표 또한 글자로 취급한다)이므로 char1은 12자리, char2는 10자리가 공백으로 마저 채워져 길이가 20이 되도록 만드는 것이다. 실제로 char1과 char2의 문자열 길이를 출력해보면 둘다 20인 것을 확인할 수 있다.

trim을 이용해 글자 뒤에 있는 공백을 제거한 후 길이를 다시 출력해보면, 그제야 Today is는 8글자, Wednesday.는 10글자로 출력하는 것을 볼 수 있다.

4. 복소수형(3_4.f90)

이번에는 복소수형 변수들의 간단한 계산을 출력해보며 해당 자료형에 익숙해져보도록 하자. 복소수는 (실수부, 허수부)순으로 작성한다고 하였으므로 a = -2.0 + 3.0$i$, b = 1.0 + 5.0$i$가 될 것이다.

결과

            (-1.00000000,8.00000000)           (-17.0000000,-7.00000000)   3.60555124

5. 논리형

1) 논리형 변수에 .TRUE.나 .FALSE.를 직접 할당해보자!(3_5_1.f90)

논리형 변수 is_true에 .true.를 할당하고 is_true를 출력해봤더니 참이라는 의미의 T가 출력된 것을 볼 수 있다.

2) 논리형 변수에 참 거짓을 판별할 수 있는 식을 할당해보자!(3_5_2.f90)

논리형 변수에는 .true.나 .false.뿐만 아니라 참 거짓을 판별할 수 있는 식이 들어가도 무방하다. 예를 들어, 3>2 라는, 참인 수식을 할당했을 때는 T가 출력되고, 2>3 이라는 거짓인 수식을 할당했을 때는 F가 출력된다.

논리형 변수 is_true에 3>2 라는 참인 수식을 할당했을 때
논리형 변수 is_true에 2>3 이라는 거짓인 수식을 할당했을 때

6. Parameter문(3_6.f90)

아래 코드를 통해 parameter와 variable의 차이를 알아보자.

이럴수가. 컴파일 과정에서 에러가 난다. 그런데 에러가 나는 것이 정상이다. 터미널을 확인해보면 b = b * 2.0 이렇게 b에 변형을 가하는 과정에서 에러가 난 것을 볼 수 있다. 그말인 즉슨  a = a + b 까지는 정상적으로 동작했다는 말인데, 이런 차이는 a는 '변수'이고 b는 '파라미터'라는 데서 온다. 파라미터는 변수와 다르게 값이 변하지 않는다. 파라미터의 값은 실행부에서 바꿀 수 없다. 위의 코드에서는 파라미터로 선언한 b의 값에 2.0을 곱해 바꾸려고 했기 때문에 에러가 뜬 것이다.

이 시리즈의 다음 글에서는 Fortran의 산술연산(Arithmetic Operation) 및 format이 없는 입출력문에 대해 다룰 예정이니 관심 있게 지켜봐주시면 좋을 것 같다!

Comments