본문으로 건너뛰기

작은 계산기 만들기

파이썬 목차반복레슨 23 / 59

목차

작은 계산기는 가격을 하나씩 받아 더하다가 빈 줄을 받으면 멈추고, 합계가 2만 원 이상이면 2,000원을 빼서 찍는 9줄 프로그램입니다. 1~5단원에서 배운 대입·입력·조건·반복·break를 한 프로그램에 모아 처음부터 끝까지 만듭니다.

지금까지는 짧은 코드를 읽고, 빈칸을 채웠습니다. 빈 화면에서 바로 쓰기는 누구에게나 어렵습니다. 그래서 할 일을 하위 목표 여섯으로 나누고, 하나씩 코드로 옮겨 조립합니다.

17단계 중 1단계. 가격 12000과 9000을 넣고 빈 줄로 끝냅니다. 하위 목표 여섯을 차례로 따라갑니다.

1무엇을 만드나 — 하위 목표 여섯

만들 계산기가 하는 일을 실행 모습으로 먼저 정합니다. 12000과 9000을 넣고 빈 줄(아무것도 치지 않고 Enter)로 끝내면 이렇게 찍혀야 합니다.

가격: 12000
가격: 9000
가격: 
합계 19,000원

이 일을 하위 목표 여섯으로 나눕니다.

하위 목표하는 일몇 번
1. 합을 0으로합계 total을 0에 붙인다한 번
2. 묻기input()으로 가격을 묻는다가격마다
3. 빈 줄이면 끝빈 줄이면 break로 묻기를 그만둔다가격마다
4. 수로 바꿔 더하기받은 글자를 int()로 바꿔 total에 더한다가격마다
5. 할인합계가 2만 원 이상이면 2,000원을 뺀다한 번
6. 쓰기합계 19,000원 꼴로 찍는다한 번

몇 번 물을지 미리 모르므로 묻기는 while True로 되풀이하고, 빈 줄에서 break로 끝냅니다(break와 continue 3절과 같은 꼴). break가 없으면 반복이 스스로 끝나지 않습니다. total은 합 모으기의 모으는 값입니다. text는 바퀴마다 방금 받은 글자를 지니는 이름이라 최근 값지기라고 부릅니다. 새 값을 받으면 옛 값은 버립니다.

2반복 안 — 묻기, 빈 줄이면 끝, 수로 바꿔 더하기

하위 목표 1~4까지 쓰고, 모인 합계를 잠깐 찍어 봅니다. 12000과 9000을 넣고 빈 줄로 끝낸 결과입니다.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
print(total)넣는 값120009000빈 줄
실행 결과
가격: 12000
가격: 9000
가격: 
21000

4~5번 줄(빈 줄이면 끝)이 6번 줄(수로 바꿔 더하기)보다 앞에 있습니다. 둘의 차례를 바꾸고 같은 값(12000, 9000, 빈 줄)을 넣으면 무엇이 찍힐까요?

total = 0
while True:
    text = input('가격: ')
    total = total + int(text)
    if text == '':
        break
print(total)넣는 값120009000빈 줄
실행 결과 보기
실행 결과
가격: 12000가격: 9000가격: Traceback (most recent call last):  File "main.py", line 4, in <module>    total = total + int(text)                    ~~~^^^^^^ValueError: invalid literal for int() with base 10: ''

예상과 다르면 그곳이 배울 곳입니다. 맨 아래 줄부터 읽습니다. ValueError는 값이 알맞지 않다는 오류이고, 빈 문자열 ''은 정수로 바꿀 수 없다(invalid literal for int())는 뜻입니다. 빈 줄을 받은 셋째 바퀴에서, 빈 줄인지 보기도 전에 4번 줄이 int('')를 계산하다 멈췄습니다. 그래서 '빈 줄이면 끝'은 늘 '수로 바꿔 더하기'보다 앞에 둡니다.

3반복 밖 — 할인과 쓰기

하위 목표 5·6을 반복 밖에 더하면 계산기가 완성됩니다.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
if total >= 20000:
    total = total - 2000
print(f'합계 {total:,}원')넣는 값120009000빈 줄
실행 결과
가격: 12000
가격: 9000
가격: 
합계 19,000원
  • 5. 할인: 다 모은 합계로 한 번만 정하므로 들여 쓰지 않은 7번 줄, 곧 반복 밖에 둡니다. elif로 여러 갈래의 '조건 세우기'처럼 big = total >= 20000으로 조건의 값에 깃발을 먼저 붙이고 if big:으로 써도 같습니다. 여기서는 줄을 줄이려고 조건을 if 줄에 바로 썼습니다.
  • 6. 쓰기: f-문자열의 {total:,}가 천 단위마다 쉼표를 찍습니다.

예제

하위 목표마다 주석 머리줄을 달면 코드를 다시 읽을 때 어디서 무엇을 하는지 바로 보입니다. 이번에는 8000과 9000을 넣고 빈 줄로 끝냅니다.

# 1. 합을 0으로
total = 0
while True:
    # 2. 묻기
    text = input('가격: ')
    # 3. 빈 줄이면 끝
    if text == '':
        break
    # 4. 수로 바꿔 더하기
    total = total + int(text)
# 5. 할인
if total >= 20000:
    total = total - 2000
# 6. 쓰기
print(f'합계 {total:,}원')넣는 값80009000빈 줄
실행 결과
가격: 8000
가격: 9000
가격: 
합계 17,000원

합계 17000이 2만 원보다 적어서 12번 줄의 조건이 False이고, 할인 없이 찍힙니다.

자주 틀리는 곳

틀린 생각: 할인 줄을 반복 안에 둬도 할인은 한 번만 빠진다.

합계가 2만 원에 이르는 때는 한 번뿐이라, 반복 안에서 봐도 할인이 한 번만 걸릴 것 같습니다. 반복 안의 if는 가격을 더할 때마다 다시 봅니다.

3절 코드의 7~8번 줄을 4칸 들여 반복 안에 두고, 12000, 9000, 5000을 넣은 뒤 빈 줄로 끝낸 결과입니다.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
    if total >= 20000:
        total = total - 2000
print(f'합계 {total:,}원')넣는 값1200090005000빈 줄
실행 결과
가격: 12000
가격: 9000
가격: 5000
가격: 
합계 22,000원

26000에서 2,000원을 한 번 빼 24,000원이어야 합니다. 그런데 9000을 더한 뒤 한 번, 5000을 더한 뒤 또 한 번 빠져 22,000원이 됐습니다. 12000과 9000처럼 마지막 가격에서 처음 2만 원에 이르면 할인이 한 번만 빠져 틀린 줄이 드러나지 않습니다. 맞춰 볼 때는 2만 원에 이른 뒤에도 가격을 더 넣어 봅니다.

맞는 규칙: 반복 안의 줄은 가격마다 실행되어, 할인 조건도 가격을 더할 때마다 다시 봅니다. 다 모은 뒤에 한 번 할 일은 반복 밖(들여 쓰지 않은 줄)에 둡니다(규칙 4).

틀린 생각: 숫자만 친 입력은 input()이 수로 돌려준다.

화면에 친 것이 숫자뿐이라 받은 값도 수일 것 같습니다. input()은 무엇을 치든 글자를 돌려줍니다.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + text
print(total)넣는 값120009000빈 줄
실행 결과
가격: 12000Traceback (most recent call last):  File "main.py", line 6, in <module>    total = total + text            ~~~~~~^~~~~~TypeError: unsupported operand type(s) for +: 'int' and 'str'

12000을 쳐도 text는 글자 '12000'에 붙습니다. 수 0에 글자를 더할 수 없어서 첫 가격에서 TypeError로 멈춥니다.

맞는 규칙: input()은 친 것이 숫자여도 글자(문자열)를 돌려줍니다. 받은 값은 int()로 수로 바꾼 뒤 더합니다.

확인 문제

1. 3절의 계산기에 15000과 5000을 넣고 빈 줄로 끝냅니다. 무엇이 찍히는지 줄마다 그대로 쓰세요.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
if total >= 20000:
    total = total - 2000
print(f'합계 {total:,}원')넣는 값150005000빈 줄
힌트

반복이 끝난 뒤의 total부터 구하고, 7번 줄의 >= 연산자가 두 값이 같을 때도 참인지 봅니다.

정답
실행 결과
가격: 15000
가격: 5000
가격: 
합계 18,000원

합계가 딱 20000이고, 20000 >= 20000은 True라서 2,000원이 빠집니다. 묻는 줄 가격:도 세 번 찍힙니다.

흔한 오답은 합계 20,000원입니다. >= 연산자를 '보다 크다'로 읽어 20000 >= 20000을 False로 본 것입니다.

2. 계산기를 하위 목표 단위로 조립합니다.

(가) 하위 목표 여섯의 차례가 섞였습니다. 처음부터 차례로 기호를 늘어놓으세요.

  • ㉠ 할인
  • ㉡ 묻기
  • ㉢ 쓰기
  • ㉣ 합을 0으로
  • ㉤ 수로 바꿔 더하기
  • ㉥ 빈 줄이면 끝

(나) 반복 부분 다섯 줄이 섞였습니다. 줄 앞의 들여쓰기는 그대로입니다. 차례로 기호를 늘어놓으세요.

㉠     total = total + int(text)
㉡ while True:
㉢     if text == '':
㉣     text = input('가격: ')
㉤         break
힌트

(가)는 1절의 표를 떠올립니다. (나)는 (가)에서 정한 하위 목표 차례에 맞춰 줄을 놓습니다.

놓은 뒤 물음

(나)를 다 맞춘 코드에서 ㉢과 ㉠을 그 차례로 놓는 까닭은 무엇일까요?

  • ① 빈 줄을 int()로 바꾸면 ValueError로 멈추기 때문
  • ② 파이썬은 if 줄을 대입문보다 먼저 실행하기 때문
  • ③ 빈 줄은 0으로 더해지지만 합계가 틀어지기 때문
정답

(가) ㉣ ㉡ ㉥ ㉤ ㉠ ㉢ — 합을 0으로 · 묻기 · 빈 줄이면 끝 · 수로 바꿔 더하기 · 할인 · 쓰기입니다.

(나) ㉡ ㉣ ㉢ ㉤ ㉠ 차례이고, 까닭은 ①입니다. 바꿔도 되는 줄은 없습니다.

while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)넣는 값120009000빈 줄
실행 결과
가격: 12000Traceback (most recent call last):  File "main.py", line 5, in <module>    total = total + int(text)            ^^^^^NameError: name 'total' is not defined

다섯 줄만 돌리면 첫 가격에서 NameError가 납니다. (가)의 맨 앞 '합을 0으로'(total = 0)를 반복 앞에 둬야 하는 까닭입니다.

①의 ValueError는 2절에서 본 오류입니다.

  • ② 줄의 종류에 따라 실행 차례가 바뀐다고 봤습니다. 파이썬은 위에서 아래로 한 줄씩 실행합니다(규칙 1).
  • ③ int('')가 0이 된다고 봤습니다. 빈 문자열은 수로 바꿀 수 없어 오류가 납니다.

3. 장보기 계산기입니다. 가격을 더하다 빈 줄이면 끝내고, 합계가 3만 원 미만이면 배송비 3,000원을 더해야 합니다. 10000과 5000을 넣었더니 18,000원이어야 할 합계가 21,000원으로 찍혔습니다. 어느 줄을 어떻게 고쳐야 할까요?

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
    if total < 30000:
        total = total + 3000
print(f'합계 {total:,}원')넣는 값100005000빈 줄
실행 결과
가격: 10000
가격: 5000
가격: 
합계 21,000원
힌트

7~8번 줄은 몇 번 실행됐을까요? 들여쓰기로 그 줄이 드는 덩어리를 봅니다.

정답

7~8번 줄의 들여쓰기를 4칸씩 줄여 반복 밖으로 꺼냅니다.

total = 0
while True:
    text = input('가격: ')
    if text == '':
        break
    total = total + int(text)
if total < 30000:
    total = total + 3000
print(f'합계 {total:,}원')넣는 값100005000빈 줄
실행 결과
가격: 10000
가격: 5000
가격: 
합계 18,000원

고치기 전에는 가격을 더할 때마다 배송비를 봐서, 10000을 더한 뒤 한 번, 5000을 더한 뒤 또 한 번 3,000원이 더해졌습니다.

다르게 고쳐도 되는 곳: 7번 줄만 0칸으로 꺼내고 8번 줄을 8칸에 그대로 둬도, 8번 줄이 if의 덩어리라 같은 결과가 나옵니다. 그래도 덩어리는 4칸씩 들여 쓰는 꼴로 맞춥니다.

흔한 오답은 7번 줄의 조건을 바꾸는 것입니다. 21,000원이 찍힌 까닭이 조건에 있다고 본 것입니다. total < 15000으로 바꾸면 이 두 값에서는 18,000원이 찍히지만, 20000 하나만 넣으면 23,000원이어야 할 합계가 20,000원으로 찍힙니다. 조건은 맞고, 자리가 틀렸습니다.

아래 자주 틀리는 곳 첫째 코드의 7번 줄 20000을 10000으로 바꾸면 찍히는 줄을 모두 봅니다.

처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

파이썬 목차로