조건문과 반복문

조건 판단과 반복을 이용한 Python 프로그램 작성

1. 목표:

조건문과 (conditions), 반복문 (loop) 이해

2. if, elif, else 조건문의 기본 구조 이해

if 조건식1:
	<명령문a>
	<명령문b>
elif 조건식2:
	<명령문c>
	<명령문d>
else:
	<명령문e>
	<명령문f>
<명령문g>
<명령문h>
<.....>
flowchart LR
	A[시작] --> B{조건식 1?}
	B -- True --> B1[명령문 a] --> B2[명령문 b]
	B -- False --> D{조건식 2?}

	D -- True --> D1[명령문 c] --> D2[명령문 d]
	D -- False --> E1[명령문 e] --> E2[명령문 f]


	B2 --> F[명령문 g]
	D2 --> F
	E2 --> F

	F --> G[명령문 h]

3. for 반복문

4. Built-in function인 range, len, enumeratefor와 함께 조합!

fruits = ["apple", "banana", "cherry"]

for i in range(len(fruits)):  # 0 ~ len(fruits)-1
   print("Index:",i,"fruit:",fruits[i])
specimen_lengths = [10.0, 12.3, 9.8, 11.5]  # cm

for i in range(len(specimen_lengths)):
    length = specimen_lengths[i]
    print("Specimen", i, "length:", length, "cm")
word = "steel"

for i in range(len(word)):
   print("Index ->", i, "character:", word[i])
fruits = ["apple", "banana", "cherry"]

for i, fruit in enumerate(fruits):
   print(i, fruit)

4.1. 논리 연산자를 활용한 조건식

여러 조건을 함께 판단할 때는 논리 연산자를 사용한다.

temperature = 750
melting_point = 660

if temperature >= melting_point and temperature < 1000:
  print("liquid state")

문자열이나 리스트에 특정 값이 포함되어 있는지도 확인할 수 있다.

element = "Fe"
metals = ["Fe", "Al", "Cu"]

if element in metals:
  print("metal")

4.2. while 반복문

while은 조건이 참(True)인 동안 명령문을 반복한다. 반복문 안에서 조건이 거짓이 되도록 값을 변경해야 무한 반복을 피할 수 있다.

n = 1

while n <= 5:
  print(n)
  n += 1

for는 반복 횟수나 순회할 자료가 정해져 있을 때, while은 종료 조건이 중심일 때 사용하면 편리하다.

4.3. breakcontinue

for number in range(1, 10):
  if number == 5:
    break
  print(number)
for number in range(1, 6):
  if number == 3:
    continue
  print(number)

4.4. 누적 계산과 반복문 속 조건문

반복문에서 계산 결과를 변수에 계속 더하는 방식을 누적 계산이라고 한다.

total = 0

for number in range(1, 6):
  total += number # total= total + number

print(total)  # 15

반복문 안에 조건문을 넣으면 특정 조건을 만족하는 값만 처리할 수 있다.

numbers = [3, 8, 11, 20, 25]

for number in numbers:
  if number % 2 == 0:
    print(number, "짝수")
  else:
    print(number, "홀수")

5. 예제

5.1. 조건문과 반복문을 활용한 기본 예제

5.1.1. 구구단 출력하기

정수 x를 입력받아 x단을 출력하시오. 입력은 2부터 9까지의 정수라고 가정한다. forrange를 사용하여 x × 1부터 x × 9까지 출력한다. 예를 들어 x = 3이면 첫 줄은 3 × 1 = 3, 마지막 줄은 3 × 9 = 27이다.

알고리즘: x를 입력받고, 곱하는 수 y를 1부터 9까지 바꾸면서 x * y를 출력한다.

5.1.2. 1부터 100까지의 정수 합 구하기

반복문으로 1부터 100까지의 정수를 더하여 합을 출력하시오. sum()은 사용하지 않고, 합을 저장할 변수를 0으로 초기화한 뒤 값을 누적한다.

5.1.3. 팩토리얼 구하기

변수 x에 저장된 정수의 팩토리얼 x!을 반복문으로 구하시오. 입력은 0 이상의 정수라고 가정한다. x!은 1부터 x까지의 정수를 곱한 값이며, 0! = 1로 정의한다. 예를 들어 x = 5이면 결과는 120이다.

5.1.4. 리스트에서 최댓값과 최솟값 찾기

다음 리스트에서 가장 큰 값과 가장 작은 값을 for와 조건문으로 구하시오. max()min()은 사용하지 않는다. 리스트는 비어 있지 않다고 가정한다.

a = [3, 4, 5, 6, 102, 3, 4, 103, 1, -10, 3, -10]

첫 번째 원소를 최댓값과 최솟값의 초기값으로 삼고, 각 원소와 비교하며 갱신한다.

5.2. 2의 제곱근 구하기.

\[x_{n+1}=x_n-\frac{(x_n)^2-2}{2x_n}\]
x=11. ## initial guess
x=x-(x**2-2)/(2*x)
print(x)
x=x-(x**2-2)/(2*x)
print(x)
x=x-(x**2-2)/(2*x)
print(x)
x=x-(x**2-2)/(2*x)
print(x)
x=11. ## initial guess
for i in range(5):
	x=x-(x**2-2)/(2*x)
	print(x)

5.3. 3의 제곱근 구하기

x=1. ## initial guess (0이어서는 안된다. 이유는?)
for n in range(7):
	x=x-(x**2-3)/(2*x)
	print(x)

5.4. 4의 제곱근 구하기

x=1. ## initial guess (0이어서는 안된다. 이유는?)
for n in range(7):
	x=x-(x**2-4)/(2*x)
	print(x)

5.5. a의 제곱근 구하기

\[x_{n+1}=x_n-\frac{(x_n)^2-a}{2x_n}\]
a=30 # a에 다른 숫자를 넣어서 반복해보자.
x=1. ## initial guess (0이어서는 안된다. 이유는?)
for i in range(7):
	x=x-(x**2-a)/(2*x)
	print(x,x**2-a)

5.6. 주양자수에 따른 부양자수와 자기양자수 출력하기

이 예제는 원자의 전자 상태를 나타내는 양자수의 허용 범위를 중첩 반복문으로 출력한다. 각 양자수의 의미와 가능한 값은 다음과 같다.

양자수 의미 가능한 값
주양자수 $n$ 전자껍질(shell)을 구분한다. 오비탈의 크기와 에너지에 관련된다. 양의 정수: $1,2,3,\ldots$
부양자수 $l$ 부껍질(subshell)과 오비탈의 모양을 구분한다. $l=0,1,2,3$은 각각 s, p, d, f에 해당한다. $0$부터 $n-1$까지의 정수
자기양자수 주어진 부껍질 안에서 오비탈의 공간적 방향을 구분한다. 아래 식의 정수 값

자기양자수는 부양자수와 다른 양자수이며, 다음 범위를 갖는다.

\[m_l=-l,-l+1,\ldots,0,\ldots,l-1,l.\]

따라서 $n$을 정하면 가능한 $l$의 범위가 정해지고, 각 $l$을 선택하면 가능한 자기양자수의 범위가 정해진다. 예를 들어 $n=3$인 전자껍질에서는 다음 상태가 가능하다.

$l$ 부껍질 자기양자수의 값 오비탈 수 최대 전자 수
0 3s 0 1 2
1 3p −1, 0, 1 3 6
2 3d −2, −1, 0, 1, 2 5 10

각 오비탈은 서로 다른 스핀양자수 $+1/2$, $-1/2$를 갖는 전자를 최대 두 개 수용한다. 따라서 아래 코드는 실제로 들어 있는 전자 수가 아니라, 해당 껍질이 수용할 수 있는 최대 전자 수를 센다.

n = 3  # 주양자수: 양의 정수
print('n:', n)
max_electrons = 0

for l_value in range(n):  # l = 0, 1, ..., n-1
    print('\tl:', l_value)  # \t는 출력에 탭 간격을 넣는다.
    print('\t\tml:')
    for ml_value in range(-l_value, l_value + 1):  # ml = -l, ..., +l
        print('\t\t\t', ml_value)
        max_electrons += 2  # 오비탈 하나당 최대 전자 두 개

print('maximum number of electrons:', max_electrons)

바깥 반복문은 부껍질을 하나씩 선택하고, 안쪽 반복문은 그 부껍질의 오비탈을 하나씩 선택한다. Python의 range는 끝값을 포함하지 않으므로, 자기양자수의 마지막 값까지 출력하려면 끝값에 1을 더해야 한다. 안쪽 반복문은 각 부껍질에서 $2l+1$회 실행된다. $n=3$이면 총 오비탈 수는 $1+3+5=9$이고, 마지막 출력의 최대 전자 수는 $18$이다. 일반적으로는

\[\text{오비탈 수}=\sum_{l=0}^{n-1}(2l+1)=n^2, \qquad \text{최대 전자 수}=2n^2\]

가 된다. n을 1, 2, 4로 바꾸어 각각 최대 전자 수가 2, 8, 32인지 확인해 보자.

연습 문제

문제 1

변수 x가 0보다 큰지 검사하는 조건식을 쓰시오.

문제 2

for i in range(3)에서 i가 차례로 갖는 값을 쓰시오.

문제 3

1부터 3까지의 정수를 출력하는 반복문의 첫 줄을 쓰시오.

문제 4

변수 temperature가 0보다 크고 100보다 작은지 검사하는 조건식을 쓰시오.

문제 5

while 반복문을 사용하여 1부터 5까지의 정수를 출력하시오.

문제 6

다음 리스트에서 짝수만 출력하도록 반복문 속에 조건문을 작성하시오.

numbers = [1, 2, 3, 4, 5, 6]

프로젝트형 연습문제

앞에서 배운 변수, 산술 연산, 문자열, 리스트, 조건문과 반복문을 조합하여 다음 두 프로그램을 작성하시오. 각 프로젝트의 제출물은 코드, 실행 결과, 확인 사례별 결과, 프로그램 흐름을 설명하는 짧은 글이다.

프로젝트 1. 10진수 → 2진수 변환기

앞에서 배운 조건문과 반복문을 활용하여, 변수 number에 저장된 정수를 2진수 문자열로 변환하는 프로그램을 작성하시오. 예를 들어 number = 13이면 1101을 출력해야 한다.

구현 요구사항

  1. 입력은 정수라고 가정한다. 음수이면 지원하지 않는 입력이라는 안내를 출력한다.
  2. 0이면 0을 출력한다.
  3. 양수이면 while 반복문과 //, %를 사용해 변환한다. bin()이나 이진수 형식 지정 기능은 사용하지 않는다.1
  4. 원래 입력값을 유지하고, 최종 결과에 10진수 입력과 2진수 문자열을 함께 출력한다.

2로 나눈 나머지는 0 또는 1이며, 가장 낮은 자리부터 얻어진다. 나머지를 문자열의 앞쪽에 차례로 붙이고, 몫을 다음 반복의 대상으로 사용하면 된다. 13에서는 몫이 6 → 3 → 1 → 0, 나머지가 1 → 0 → 1 → 1이므로 결과는 1101이다.

확인 사례

입력 기대하는 결과
0 0
1 1
2 10
13 1101
32 100000
−3 음수를 지원하지 않는다는 안내

프로젝트 2. 경도 측정값 검사와 결과 요약

여러 시편의 경도 측정값을 저장한 리스트를 검사하고, 각 시편의 판정과 전체 결과를 출력하는 프로그램을 작성하시오. 측정값은 모두 동일한 경도 척도와 시험 조건에서 얻은 수치라고 가정한다.

hardness = [110, 125, -1, 138, 142, 119, 166, 130]

다음 기준은 프로그래밍 연습을 위해 정한 가상의 기준이며, 실제 재료의 합격 규격을 뜻하지 않는다.

측정값 처리
0 이하 잘못된 측정값으로 제외
0 초과, 120 미만 기준 미달
120 이상, 150 이하 합격
150 초과 기준 초과

구현 요구사항

  1. for 반복문으로 측정값을 하나씩 읽고, 시편 번호와 판정을 출력한다. 시편 번호는 1부터 시작한다.
  2. if, elif, else로 판정하고, 잘못된 값은 평균 계산에서 제외한다.
  3. 유효한 값의 합과 개수, 잘못된 값의 개수, 기준 미달·합격·기준 초과의 개수를 누적한다.
  4. 반복이 끝나면 각 개수와 유효한 값의 평균을 출력한다.
  5. 유효한 값이 없으면 평균 대신 안내를 출력한다. 빈 리스트에서도 오류가 나지 않아야 한다.

평균은 유효한 측정값의 합을 유효한 값의 개수로 나누어 계산한다. 위 데이터의 결과는 유효값 7개, 잘못된 값 1개, 기준 미달 2개, 합격 4개, 기준 초과 1개이며, 평균은 약 132.86이다.

확인 사례

데이터 확인할 동작
위의 예시 리스트 판정별 개수와 평균이 예시 결과와 일치하는가?
[120, 150] 두 값 모두 합격이고 평균이 135인가?
[0, -1] 잘못된 값 2개로 집계하고, 평균을 계산하지 않는가?
[] 모든 개수가 0이고, 유효한 값이 없다는 안내를 출력하는가?

선택 과제: 판정별 개수를 딕셔너리에 저장하고, 합격률을 유효한 값의 개수를 기준으로 계산하시오.

  1. 10진수 n을 2로 나누면 항상 n = 2q + r로 나타낼 수 있다. 여기서 q는 몫이고 r은 나머지(0 또는 1)이다. 따라서 n % 2로 가장 오른쪽 이진수 자리를 얻고, n // 2로 다음 자리를 구할 수 있는 더 작은 수를 만든다. 몫이 0이 될 때까지 이 과정을 반복하면 나머지는 낮은 자리부터 얻어진다. 예를 들어 13(q, r) = (6, 1) → (3, 0) → (1, 1) → (0, 1)이므로 나머지를 역순으로 읽어 1101이 된다. 코드에서는 나머지를 문자열의 앞에 붙여 역순으로 읽는 효과를 낸다.