프로그래밍

연산자

기호 하나가 무슨 일을 하는지는
양쪽에 놓인 값이 정합니다.

학습 목표

  1. 산술 연산자로 계산할 수 있고, 두 가지 나눗셈이 어떻게 다른지 설명할 수 있다.
  2. 문자열에 쓰는 더하기와 곱하기가 무엇을 하는지 설명할 수 있다.
  3. 비교 연산과 논리 연산으로 조건식을 만들 수 있고, 그 결과가 참·거짓임을 안다.
  4. 값의 이진수 자릿수(비트)를 직접 다루는 연산이 무엇인지 알고, 어디에 쓰이는지 말할 수 있다.

산술 연산자

계산기와 가장 다른 점은 나눗셈이 두 가지라는 것입니다.

print(7 + 3)     # 10
print(7 - 3)     # 4
print(7 * 3)     # 21
print(7 / 3)     # 2.3333333333333335   나누면 「언제나」 실수가 된다
print(7 // 3)    # 2                    몫만 남기고 싶을 때
print(7 % 3)     # 1                    나머지
print(7 ** 3)    # 343                  거듭제곱
연산자 하는 일 특징
+ - * 더하기·빼기·곱하기 계산기와 같다
/ 나누기 결과가 언제나 실수다
// 몫 나눈 결과보다 크지 않은 가장 큰 정수로 내린다
% 나머지 퍼센트가 아니다
** 거듭제곱 2 ** 10은 1024

/로 나누면 딱 떨어져도 실수가 됩니다

print(6 / 3)      # 2.0    딱 나누어떨어져도 실수다
print(6 // 3)     # 2      정수 결과가 필요하면 이쪽
print(-7 // 2)    # -4     내림이라서 -3이 아니다

6 / 3이 2가 아니라 2.0입니다. 화면에 출력된 2.0을 보고 「왜 소수점이 붙지?」 하고 놀랐다면 이 때문입니다. 결과를 정수로 얻으려면 //를 씁니다(양쪽이 정수일 때).

//는 버림이 아니라 내림입니다. -7 // 2는 -3이 아니라 -4가 됩니다 — 음수를 다룰 때만 드러나는 차이입니다. 나머지도 이 몫에 맞춰 계산되므로 -7 % 2는 1입니다. C처럼 몫의 소수점 아래를 그냥 버리는 언어에서는 같은 식의 결과가 -3과 -1이므로, 음수를 나눌 때는 언어마다 규칙을 확인합니다.

나머지는 어디에 쓰는가

  • 짝수인지 홀수인지 — n % 2가 0이면 짝수다.
  • 단위를 바꿀 때 — 135초는 135 // 60분 135 % 60초.
  • 몇 개마다 한 번 — i % 10이 0일 때만, 즉 i가 10의 배수일 때만 줄을 바꾼다.
sec = int(input("초를 입력하세요: "))

print(sec, "초는", sec // 60, "분", sec % 60, "초입니다")

여기서 //를 /로 바꾸면 135를 입력했을 때 「2.25 분」처럼 출력됩니다. 몫과 나머지는 한 쌍이라 이런 계산에서 늘 함께 씁니다.

스스로 확인

며칠 뒤가 무슨 요일인지 계산하는 프로그램을 만든다면 %를 어디에 쓸 수 있을까요?

문자열에 쓰는 연산자

같은 연산자라도 양쪽이 문자열이면 하는 일이 달라집니다.

print("안녕" + "하세요")   # 안녕하세요   이어 붙인다
print("-" * 20)           # --------------------   반복한다
print("가" * 3)           # 가가가

# print("점수: " + 90)    # 오류. 문자열과 숫자는 이어 붙일 수 없다
print("점수: " + str(90)) # 점수: 90   한쪽의 자료형을 맞춰 주어야 한다

+는 이어 붙인다

"안녕" + "하세요"는 안녕하세요. 양쪽이 모두 문자열이어야 합니다.

*는 반복한다

"-" * 20은 -를 20번 반복해 구분선 하나를 만듭니다. 손으로 스무 번 입력하지 않아도 됩니다.

문자열과 숫자는 이어 붙일 수 없습니다

"점수: " + 90은 오류입니다. 파이썬은 이어 붙이라는 것인지 더하라는 것인지 판단할 수 없어 추측하지 않고 오류를 냅니다. str(90)으로 한쪽의 자료형을 맞춰 주어야 합니다.

같은 일을 쉼표로 나열해서 할 수도 있습니다 — print("점수:", 90)은 오류 없이 실행됩니다. 다만 공백이 하나 들어갑니다.

스스로 확인

"=" * 10 + "메뉴" + "=" * 10은 어떤 문자열이 될까요? *와 + 가운데 어느 것이 먼저 계산되는지도 생각해 보세요.

비교 연산자와 논리 연산자

조건식을 만들 때 쓰는 연산자입니다.

print(7 > 3)      # True
print(7 < 3)      # False
print(7 == 7)     # True    같은지 비교하는 것은 등호 두 개
print(7 != 7)     # False
print("a" < "b")  # True    문자열도 비교할 수 있다 (앞 글자부터 문자 코드 순서로)

결과는 True와 False

비교 연산의 결과는 참 또는 거짓 가운데 하나인 논리값입니다. True와 False는 첫 글자가 대문자라는 점을 눈여겨보세요.

같은지 비교하는 것은 ==, 대입하는 것은 =

x = 5는 x에 5를 대입하고, x == 5는 x가 5와 같은지 비교합니다. 자주 하는 실수이니 조건식을 쓸 때마다 등호 개수를 확인하세요.

수학처럼 이어 쓸 수 있습니다

score = 85
print(80 <= score < 90)   # True   수학처럼 이어 쓸 수 있다

80 <= score < 90이 의도한 대로 동작합니다. 많은 언어에서는 이렇게 쓰면 엉뚱한 결과가 나오거나 오류가 나지만, 파이썬은 「80 이상이면서 90 미만」으로 해석합니다.

조건 여러 개를 묶을 때는 논리 연산자를 씁니다. 기호가 아니라 영어 단어라서 소리 내어 읽으면 뜻이 그대로 드러납니다.

score = 85
print(score >= 80 and score < 90)   # True    둘 다 참이어야 참
print(score < 60 or score > 90)     # False   둘 다 거짓이라 거짓 (하나라도 참이면 참)
print(not score >= 80)              # False   뒤집는다
연산자 읽는 법 참이 되는 경우
and 그리고 양쪽이 모두 참일 때
or 또는 하나라도 참일 때
not 아니다 뒤에 오는 조건이 거짓일 때

결과가 정해지면 오른쪽은 아예 계산하지 않습니다

total = 100
count = 0                        # 아직 아무도 응답하지 않았다

if count != 0 and total / count >= 60:
    print("평균이 60점 이상입니다")
else:
    print("아직 평균을 낼 수 없습니다")   # 이쪽이 실행된다

# count가 0이라 왼쪽이 거짓 -> 오른쪽 total / count는 「계산되지 않는다」
# 만약 계산했다면 0으로 나누게 되어 바로 오류가 난다

이 코드의 if는 조건식이 참이면 바로 아래 줄을, 거짓이면 else 아래 줄을 실행하는 문장으로, 「선택 구조」 강의노트에서 자세히 배웁니다. and는 왼쪽이 거짓이면 오른쪽을 계산할 필요도 없이 거짓입니다. 그래서 오른쪽을 건너뜁니다 — count가 0이므로 total / count는 아예 계산되지 않습니다.

만약 계산했다면 0으로 나누게 되어 바로 오류가 납니다. 이처럼 결과가 정해지는 순간 나머지를 계산하지 않는 성질을 단축 평가(short-circuit evaluation)라고 합니다. 덕분에 「먼저 안전한지 확인하고, 안전할 때만 계산한다」를 한 줄로 쓸 수 있습니다. 확인하는 조건을 반드시 왼쪽에 두어야 합니다.

스스로 확인

점수가 60점 미만이거나 100점을 넘으면 「잘못된 값」으로 판단하려면 조건식을 어떻게 쓸까요?

비트 연산자

수를 이진수로 나타내고, 자릿수(비트) 하나하나를 다루는 연산입니다.

지금까지의 연산은 수를 하나의 값으로 다뤘습니다. 비트 연산은 같은 수를 0과 1로 이루어진 이진수로 보고, 이진수의 자릿수인 비트(bit)마다 따로 계산합니다.

a = 12          # 이진수로 1100
b = 10          # 이진수로 1010

print(a & b)    # 8    1000   둘 다 1인 비트만 1
print(a | b)    # 14   1110   하나라도 1이면 1
print(a ^ b)    # 6    0110   서로 다르면 1
print(a << 1)   # 24   11000  왼쪽으로 1비트 이동 = 2배
print(a >> 1)   # 6    110    오른쪽으로 1비트 이동 = 2로 나눈 몫
연산자 비트마다 하는 일 12와 10의 예
& 둘 다 1인 비트만 1 1100 & 1010 = 1000 = 8
| 하나라도 1이면 1 1100 | 1010 = 1110 = 14
^ 서로 다르면 1 1100 ^ 1010 = 0110 = 6
<< 비트를 왼쪽으로 이동 1100 → 11000, 값은 2배
>> 비트를 오른쪽으로 이동 1100 → 110, 값은 2로 나눈 몫

and와 &는 다릅니다

영어 단어로 된 and·or는 양쪽 값을 각각 참 또는 거짓으로 판단해 조건을 묶습니다. 기호인 &·|는 비트 하나하나를 계산합니다. 이름이 비슷해 헷갈리기 쉽지만 하는 일이 전혀 다릅니다. 조건을 묶을 때는 영어 단어로 된 쪽을 씁니다.

어디에 쓰이나

켜짐/꺼짐 같은 참·거짓 여러 개를 수 하나에 모아 저장할 때, 그리고 색상 값처럼 수 하나에 여러 정보가 들어 있을 때 씁니다. 일상적인 계산에는 잘 쓰이지 않으므로 「비트마다 따로 계산하는 연산이 있다」는 것까지만 알아 두면 됩니다.

스스로 확인

13 & 1의 결과로 무엇을 알 수 있을까요? 13 대신 다른 수를 넣어 보며 규칙을 찾아보세요.

핵심 정리

나눗셈 둘

/의 결과는 딱 떨어져도 실수다. 정수끼리 나누어 정수 결과를 얻으려면 //. //는 버림이 아니라 내림이다.

문자열 연산

+는 이어 붙이고 *는 반복한다. 문자열과 숫자는 이어 붙일 수 없다 — str로 자료형을 맞추거나 쉼표로 나열한다.

비교와 논리 연산

결과는 True·False. 조건을 묶을 때는 and·or·not. 80 <= score < 90처럼 이어 써도 의도한 대로 동작한다.

단축 평가

and의 왼쪽이 거짓이면 오른쪽을 계산하지 않는다. 확인하는 조건을 왼쪽에 두면 위험한 계산을 막을 수 있다.

비트 연산

수를 이진수로 보고 비트마다 따로 계산한다. &·|는 비트 하나하나를 계산하므로, 조건을 묶는 and·or와 하는 일이 다르다.

확인 퀴즈

배운 내용을 확인해 봅시다.

1. print(6 / 3)의 결과는?

2. print("점수: " + 90)을 고치는 방법으로 맞지 않는 것은?

3. 다음 중 틀린 설명은?