Chapter 1

좌표평면과 함수 그래프

입력과 출력을 그림으로 연결하기
핵심 질문

함수 그래프는 어떤 점들을 모아 놓은 그림일까?

좌표평면과 함수 그래프

핵심 질문

좌표평면에서 함수 그래프는 무엇을 보여 주는 그림일까?

교과서 설명

좌표평면은 가로축 와 세로축 로 위치를 나타내는 도구다. 함수는 입력 에 대해 출력 를 정하는 규칙이다.

이 식은 를 넣으면 을 출력한다는 뜻이다. 그래프는 많은 입력과 출력을 점으로 찍어 연결한 그림이다.

그래프 위의 점 는 “입력 를 넣었을 때 출력이 이다”라는 기록이다.

함수에서 꼭 지켜야 할 조건은 같은 입력에는 출력이 하나만 정해진다는 것이다. 수식으로 쓰면

이다. 그래서 가 동시에 같은 함수의 그래프 위에 있을 수는 없다. 이 조건이 있어야 을 하나 고를 때 표본값 도 하나로 정해진다.

연속 그래프는 점이 끊기지 않고 이어진 그림이다. 하지만 컴퓨터는 무한히 많은 점을 저장하지 못하므로 몇 개의 점만 골라 저장한다.

이렇게 고른 값들의 목록이 뒤에서 말하는 신호 배열과 연결된다.

세부 정의와 표본화 과정

대학 교재에서는 함수를 단순한 “식”보다 조금 넓게 본다. 함수 는 입력 집합의 각 원소 에 출력 집합의 원소 를 하나씩 대응시키는 규칙이다. 그래프는 이 대응 관계를 좌표평면에 모은 집합이다.

여기서 는 함수가 정의되는 입력 범위다. 컴퓨터가 함수를 다룰 때는 전체를 저장하지 않고, 일정한 간격으로 고른 점만 저장한다. 시작점을 , 간격을 라고 하면 번째 표본은 다음처럼 쓸 수 있다.

여기서 는 “델타 x”라고 읽고, 값이 한 표본에서 다음 표본으로 갈 때마다 얼마나 늘어나는지를 뜻한다. 즉 는 새로운 함수나 특별한 점이 아니라, 축에서 표본을 찍는 한 칸의 폭이다. 예를 들어 , 라면 표본의 좌표는 처럼 0.5씩 늘어난다. 그래서 는 시작점 에서 오른쪽으로 칸 이동한 거리이고, 는 그때의 실제 좌표다.

이때 은 연속 함수 자체가 아니라 길이 인 벡터다. 나중에 DFT와 FFT가 다루는 대상도 “무한히 이어진 그래프”가 아니라 이렇게 유한하게 잘라 낸 값들의 배열이다.

중요한 점은 역방향이 하나로 정해지지 않는다는 것이다. 같은 네 점을 지나는 연속 그래프는 무수히 많을 수 있다. 따라서 표본 배열만 보고 원래 그래프를 완벽히 복원하려면, 신호가 충분히 부드럽다거나 특정 주파수 이하만 가진다는 추가 조건이 필요하다.

직관 비유

함수는 자동판매기와 비슷하다. 라는 동전을 넣으면 라는 음료가 나온다. 그래프는 모든 동전과 음료의 관계를 지도처럼 펼친 것이다.

예제

, 이므로 두 점 , 가 그래프 위에 있다.

예를 들어 을 네 점에서만 보면 다음 배열처럼 저장할 수 있다.

주의할 점이 있다. 그래프를 배열로 자르면 저장하기 쉬워지지만, 고르지 않은 중간 부분의 정보는 사라진다. 그래서 샘플을 너무 적게 찍으면 원래 그래프를 잘못 상상할 수 있다.

손풀이 체크

  1. 일 때 를 배열로 쓰면?

    답 보기

    [1,3,5][1,3,5]

  2. 위에 있는 이유는?

    답 보기

    32=93^2=9이기 때문이다.

  3. 그래프를 네 점만 찍어 배열로 저장하면 무엇을 잃을 수 있을까?

    답 보기

    네 점 사이에서 그래프가 어떻게 움직였는지에 대한 정보가 줄어든다.

다음으로 이어지는 생각

좌표평면에서 점과 그래프를 읽을 수 있으면, 원 위의 점을 , 로 읽는 단위원도 더 쉽게 볼 수 있다.

이번 장에서 기억할 3문장

  1. 함수 그래프의 점 (x,y)(x,y)는 입력 xx에 대한 출력 yy를 뜻한다.
  2. 샘플 배열은 연속 그래프에서 몇 개의 값만 골라 저장한 것이다.
  3. 샘플이 적으면 점 사이의 움직임은 잃어버릴 수 있다.

C++ Practice

C++로 확인하기

함수 f(x)f(x)를 값 표와 배열로 바꾸는 연습

#include <iostream>
#include <vector>

using namespace std;

int f(int x) {
    return x * x;
}

int main() {
    vector<int> xs = {0, 1, 2, 3};
    vector<int> samples;

    for (int x : xs) {
        samples.push_back(f(x));
    }

    cout << "f(x)=x^2 samples: ";
    for (int value : samples) {
        cout << value << ' ';
    }
    cout << "\n";
}

연습: f(x)f(x)2x+12x+1이나 x21x^2-1로 바꿔서 배열이 어떻게 달라지는지 확인해 보자.