ISBN 978-89-7050-850-4 978-0-13-274718-9
Y. Daniel Liang 길준민 · 정재화
Chapter 5
루프
5.1 들어가기
5.2 while 문
5.3 for 루프
5.4 중첩 루프
5.5 수치 오차 최소화하기
5.6 사례 연구
5.7 break와 continue 키워드
5.8 사례 연구: 소수 출력하기
5.9 사례 연구: 랜덤 워크
• 하나의 문자열(예를 들면, ‘프로그래밍은 재미있습니다!’)을 100번 출력해야 한 다고 가정해보자.
• 다음의 명령문을 아래와 같이 100번 입력한다는 것은 매우 지루한 작업일 것이 다.
CONTENTS
학습하기에 앞서
Ch5 루프
print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!")
… print("프로그래밍은 재미있습니다!") print("프로그래밍은 재미있습니다!")
100번
print("프로그래밍은 재미있습니다!");
• while 루프를 사용하여 반복적 명령문을 실행하는 프로그램을 작성할 수 있다(5.2 절).
• 루프 설계 전략을 따라 루프를 개발할 수 있다(5.2.1~5.2.3 절).
• 사용자 확인을 통해 루프를 제어할 수 있다(5.2.4 절).
• 감시 값을 이용하여 루프를 제어할 수 있다(5.2.5절).
• 직접 키보드 입력 대신 입력 재지정을 이용하여 파일로부터 많은 양의 데이터를 입력 받고, 출력 재지정을 사용하여 출력 데이터를 파일에 저장할 수 있다(5.2.6절).
• for 루프를 사용하여 계수 제어 루프를 구현할 수 있다(5.3절).
• 중첩 루프를 작성할 수 있다(5.4절).
• 수치적 오류를 최소화하는 기법을 이해할 수 있다(5.5절).
• 다양한 예제(GCD, 미래학자금, 몬테카를로 시뮬레이션, 소수)를 통해 루프를 이해할 수 있다(5.6, 5.8 절).
• break 문과 continue 문으로 제어하는 프로그램을 구현할 수 있다(5.7절).
• 랜덤워크 시뮬레이션에 루프를 적용할 수 있다(5.9절).
학습목표
4
학습하기에 앞서 해결 방법
count = 0
while count < 100:
print("프로그래밍은 재미있습니다!") count = count + 1
while 루프 실행 흐름도
명령문(들)
루프 몸체
True
False
루프-계속-조건
count = 0
while count < 100:
print("프로그래밍은 재미있습니다!") count = count + 1
while
루프-계속-조건:# 루프 몸체
명령문(들)구문형식
print(" 프로그래밍은 재미있습니다!") count = count + 1
True
count = 0
False
count < 100
6
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
while 루프 트레이스
count 초기화
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
(count < 2)는 True
8
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
프로그래밍은 재미있습니다! 출력
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
count 를 1 증가 count 는 이제 1
10
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
count 는 1이기 때문에
(count < 2) 는 아직 True
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
프로그래밍은 재미있습니다! 출력
12
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
count 를 1 증가
count 는 이제 2
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
count 는 2이기 때문에 (count < 2) 는 이제 False
14
while 루프 트레이스
count = 0
while count < 2:
print("프로그래밍은 재미있습니다!") count = count + 1
루프가 종료
루프 이후의 다음 명령문을 실행
• while 문을 이용하여 “프로그래밍은 재미있습니다”를 10회 출력하자!
• while 문을 이용하여 “프로그래밍은 재미있습니다”를 20회 출력하자!
• while 문을 이용하여 “프로그래밍은 재미있습니다”를 20회 출력하자!
• 이때 각 줄에 출력 횟수를 출력하자
16
Lab
SubtractionQuizLoop
• 뺄셈 학습기는 각 실행 시 단지 하나의 문제만을 생성한다.
• 이번에는 루프를 사용하여 반복적으로 문제를 생성하도록 작성할 수 있다. 이 문제는 다섯 개의 문제를 생성하고 학생이 모든 문제에 답한 이후에 정답의 개 수를 출력한다.
뺄셈 학습기
실행
18
뺄셈 학습기
• 0 이상 100이하 사이의 정수를 랜덤하게 생성하는 프로그램을 작성해보자.
• 프로그램은 랜덤하게 생성된 숫자가 사용자의 입력과 일치할 때까지 계속적으 로 입력 받는다.
• 각 사용자 입력에 대해, 프로그램은 큰지 작은지 응답하여 사용자가 지능적으 로 다음 입력을 선택할 수 있게 한다.
• 다음은 실행 예이다.
사례연구: 숫자 맞히기
GuessNumber 실행
GuessNumberOneTime 실행
20
import random
# 사용자가 맞춰야하는 마법수를 생성한다.
number = random.randint(0, 100)
print("0과 100 사이의 마법수를 맞춰보세요.")
# 사용자로부터 추측값을 입력받는다.
guess = eval(input("마법수는 무엇일까요?: ")) if guess == number:
print("정답, 마법수는" + str(number), "입니다.") elif guess > number:
print("너무 큽니다.") else:
print("너무 작습니다.")
22
import random
# 사용자가 맞춰야하는 마법수를 생성한다.
number = random.randint(0, 100)
print("0과 100 사이의 마법수를 맞춰보세요.") guess = -1
while guess != number:
# 사용자로부터 추측값을 입력받는다.
guess = eval(input("마법수는 무엇일까요?: "))
if guess == number:
print("정답, 마법수는", number, "입니다.") elif guess > number:
print("너무 큽니다.") else:
print("너무 작습니다.")
• 때때로 루프의 반복 횟수가 사전에 정해지지 않는 경우가 있다. 이러한 경우 반복의 끝을 의미하는 입력값을 사용할 수 있다. 이러한 입력값을 감시 값이라 고 한다.
• 불특정 개수의 정수를 읽고 합계를 계산하는 프로그램을 작성하시오. 입력 0 은 입력의 끝을 나타낸다.
감시 값을 사용하여 루프 종료하기
SentinelValue 실행
24
수행결과
26
과과
data = eval(input("정수를 입력하세요 (입력이 0이면 " + \ "종료됩니다): "))
# 입력이 0이 아닐 때까지 데이터를 계속 읽는다.
sum = 0
while data != 0:
sum += data
data = eval(input("정수를 입력하세요 (입력이 0이면 " + \ "종료됩니다): "))
print("합계는", sum, "입니다.")
• 루프 제어에서 동등 검사에 부동소수점 값을 사용하면 문제가 발생한다. 부동소수점 값은 근사치 이기 때문에 부정확한 계수 값으로 이어질 수 있다. 이번 예제에서는 data는 정수값으로 사용되었 다. 1 + 0.9 + 0.8 + … + 0.1을 계산하는 다음의 코드를 생각해 보자.
• 변수 item은 1에서 시작하고 루프 몸체가 실행될 때마다 0.1씩 감소한다. 루프는 item이 0이 될 때 종료되어야 한다. 그러나 부동소수점 연산은 근사치를 사용하기 때문에 item이 정확하게 0이 될 것이라고 보장할 수 없다. 이 루프는 겉으로 문제가 없는 것처럼 보이지만 실제로 무한루프이 다.
주의
부동소수점 값 사용
item = 1 sum = 0
while item != 0: # item이 0이 될 것 이라고 보장할 수 없다 sum += item
item -= 0.1 print(sum)
for Loops
for i in range(initialValue, endValue):
# 루프 몸체
구문형식
i = initialValue # 루프 제어 변수를 초기화한다.
while i < endValue:
# 루프 몸체 …
i++ # 루프 제어 변수를 조정한다.
28
루프의 순환 횟수를 정확하게 알 경우 for-loop가 편리하다
range(a, b)
range(b)
30
range(a, b, step)
range(a, b, step)
32
다음을 입력하고 수행해보시오
for i in str('Hello'):
print(i)
print('fruits are : ')
for l in ['apple','banana','peach','lemon']:
print(l)
• 문제: 중첩 루프를 사용하여 구구단 표를 출력하는 프로그램을 작성하시오.
중첩 루프
MultiplicationTable 실행
34
구구단 표
36
print(" 구구단표")
# 표 머리글을 출력한다
print(" |", end = '') for j in range(1, 10):
print(" ", j, end = '') print() # 새로운 행으로 건너뛴다.
print("---")
# 표 몸체를 출력한다.
for i in range(1, 10):
print(i, "|", end = '') for j in range(1, 10):
# 곱셈 결과를 출력하고 적절하게 정렬한다.
print(format(i * j, '4d'), end = '')
print()# 새로운 행으로 건너뛴다.
• 부동소수점 수의 수치 오류는 피할 수 없다. 이번 절에서는 이러한 오류를 어 떻게 최소화할 수 있는지 예제를 통해 살펴본다.
• 예제 프로그램은 0.01로 시작해서 1.0에서 끝나는 수열의 합을 구한다. 수열 의 수는 0.01 + 0.02 + 0.03 등과 같이 0.01씩 증가한다.
수치 오차 최소화하기
TestSum 실행
38
• 올해 대학 등록금이 1천만 원이고 매년 7%씩 증가한다고 하자. 몇 년 안에 등 록금이 두 배가 되겠는가?
사례 연구: 미래 등록금 계산하기
FutureTuition 실행
사례 연구: 미래 등록금 계산하기
year = 0 # Year 0 tuition = 10000 year += 1 # Year 1 tuition = tuition * 1.07 year += 1 # Year 2 tuition = tuition * 1.07 year += 1 # Year 3 tuition = tuition * 1.07
FutureTuition 실행
40
• 몬테카를로 시뮬레이션(Monte Carlo simulation)은 문제해결을 위해 랜덤 숫자와 확률을 사용한다.
• 몬테카를로 시뮬레이션은 계산 수학, 물리학, 화학 및 재무 분야 에서 널리 사 용된다. 이제 원주율(π)을 추정하기 위해 몬테카를로 시뮬레이션을 사용한 예 제를 살펴보자.
몬테 카를로 시뮬레이션
1
-1 -1
4
1
42
import random
NUMBER_OF_TRIALS = 5000000 # 상수 numberOfHits = 0
for i in range(NUMBER_OF_TRIALS):
x = random.random() * 2 - 1 y = random.random() * 2 - 1 if x * x + y * y <= 1:
numberOfHits += 1
pi = 4 * numberOfHits / NUMBER_OF_TRIALS
print("PI는", pi, "입니다.")
• break는 루프 내부에서 루프를 즉시 종료시킬 수 있다.
• continue는 루프 내부에서 continue문 아래의 문장을 건너뛴다. 하지말 루프 는 종료되지 않는다
break 와 continue 키워드 사용하기
sum = 0 number = 0
while number < 20:
number += 1 sum += number if sum >= 100:
break
print("마지막 숫자는", number, "입니다.") print("합계는", sum, "입니다.")
TestBreak.py
루프부터 빠져 나온다
44
루프내부에서 sum의 값이 100 이상이 되면 더이상 루프를 수행하지 않고 빠져 나온다
TestContinue.py
sum = 0 number = 0
while (number < 20):
number += 1
if (number == 10 or number == 11):
continue sum += number
print("The sum is ", sum) 반복의 맨 끝
으로 건너뛴 다
루프내부에서 number가 10혹은 11이 되면 sum에 더하지 않는다.
하지만 루프는 20이 될때까지 계속 진행된다
• 숫자 맞히기 프로그램에 대해서 살펴보았다.
• 이제, break 문을 사용하여 숫자 맞히기 프로그램을 재작성 할 수 있다.
숫자 맞히기 다시 생각하기
GuessNumberUsingBreak 실행
46
• 1보다 큰 정수 중 1과 자기 자신으로만 나누어지는 수를 소수(prime number)라고 한다.
• 예를 들어, 2, 3, 5와 7은 소수이나 4, 6, 8, 9는 소수가 아니다.
• 첫 50개의 소수를 한 행에 10개씩 5개의 행에 출력하는 문제는 다음과 같은 작업으로 분해될 수 있다.
■ 주어진 수가 소수인지 결정한다.
■ 2, 3, 4, 5, 6, …에 대하여 숫자가 소수인지 검사한다.
■ 소수의 개수를 센다.
■ 각 소수를 출력하고 한 행에 10개씩 숫자가 들어가도록 출력한다.
사례 연구: 소수 출력하기
PrimeNumber 실행
48
NUMBER_OF_PRIMES = 50 # 출력되어야 하는 소수의 개수
NUMBER_OF_PRIMES_PER_LINE = 10 # 한 행당 출력되는 소수의 개수 count = 0 # 소수의 개수를 센다.
number = 2 # 소수성을 검사해야 하는 숫자 print("첫 50개의 소수")
# 반복적으로 소수를 찾는다.
while count < NUMBER_OF_PRIMES:
# number가 수소라고 가정한다.
isPrime = True # 현재 number가 소수인가?
# number가 소수인지 검사한다.
divisor = 2
while divisor <= number / 2:
if number % divisor == 0:
# 참이라면 number는 소수가 아니다.
isPrime = False # isPrime을 거짓으로 설정한다.
break # while 루프를 종료한다.
divisor += 1
# 소수를 출력하고 count를 증가시킨다.
if isPrime:
count += 1 # count를 증가시킨다.
print(format(number, '5d'), end = '')
if count % NUMBER_OF_PRIMES_PER_LINE == 0:
# number를 출력하고 다음 행으로 진행한다.
print() # 다음행으로 건너뛴다.
# 다음 number가 소수인지 검사한다.
number += 1
number 가 소수인지 검사하는 모듈
# number가 소수인지 검사한다.
divisor = 2
while divisor <= number / 2:
if number % divisor == 0:
# 참이라면 number는 소수가 아니다.
isPrime = False # isPrime을 거짓으로 설정한다.
break # while 루프를 종료한다.
divisor += 1
ISBN 978-89-7050-850-4 978-0-13-274718-9