E,AHRSS

함수

last modified: 2015-04-04 21:51:04 Contributors

Contents

1. 수학에서의 함수
1.1. 개요 및 정의
1.2. 함수의 전사와 단사
1.3. 함수의 합성, 항등함수, 역함수
1.4. 몰라도 되는 함수의 역사
1.5. 관련 항목
2. 프로그래밍에서의 함수
2.1. 함수의 장점
2.2. 함수 호출시 오버헤드
2.3. 수학 함수와의 관계
3. 걸그룹 f(x)의 별명
4. 소금기가 많은 짠물. 鹹水
5. 자일대우버스 FX시리즈의 별명
6. 군함의 앞부분. 艦首


1. 수학에서의 함수

1.1. 개요 및 정의

함수(函數, function) f:X→Y[1]란 집합 X와 집합 Y의 원소 사이에 주어진 다음 성질을 만족하는 대응으로 정의된다.
  1. 집합 X의 원소 하나에는 Y의 원소 하나만이 대응된다. 수식으로 표현하면 a=b ⇒ f(a)=f(b). 다만 Y의 원소 하나에 X의 원소 여러개가 대응될 수는 있다.
  2. 집합 X의 원소는 모두 대응되는 집합 Y의 원소가 있다.
X는 솔로여도 안되고 양다리를 걸쳐도 안된다
여기서 집합 X를 f의 정의역(domain)이라고 하고, Y를 공역(codomain)이라고 한다. 보통 x∈X에 대응하는 Y의 원소를 f(x) [2]라 쓴다. 치역(range)은 이 대응되는 원소 f(x)들을 모두 모은 집합으로, 종종 f(X)로 표기된다.

주의할 점은, 정의역 또는 공역이 다르면 같은 함수인 것처럼 보여도 다른 함수라고 한다. 예를 들어, f(x)=x²이라는 함수가 정수에서 정의된 것과, 실수에서 정의된 것은 서로 다른 함수다. 복소수에서 정의되면 또 달라진다. [3] 수능 공부를 하는 학생이라면 여기까지 구분할 필요는 없을 것 같다.

대부분의 경우 보통 함수 하면 실수 집합(의 부분집합)을 정의역과 공역으로 갖는 실함수(real-valued function)를 떠올리게 되고, 이는 우리가 흔히 생각하는 두 변수의 대응관계로서의 개념과 일치한다. 예를 들어 일차함수 f(x)=ax 같은 경우는 소위 말하는 독립변수(Independant Value) x와 종속변수(Dependant Value) y=f(x)가 정비례한다는 관계를 나타냈다고 해석할 수 있다. 다만 이 변수니 관계니 하는 이야기는 위의 일반적인 함수의 정의와는 이제 전혀 맞지 않는다.

좌표 평면의 x축을 독립변수로 하고 각각의 x값에 대응하는 y값으로 수많은 점 (x,y)을 찍어 선으로 연결하면 그래프를 만들 수 있는데, 이런 식으로 좌표평면 위에서 만들어지는 도형들에 대해 연구하는 학문이 석기하학이다. y=ax+b 꼴의 함수로 그래프를 그리면 이 되고, y=(x-a)2+b는 포물선, (x-a)2+(y-b)2=r2이 되는 식. 물론 초등적인 의미에서 원은 함수가 아니다. (x)2+(y)2=1이라는 원의 방정식에 대해 x=1/2 에 대응하는 값이 두개가 나오기 때문.

종종 초등/중등교육과정에서 함수는 입력값을 넣으면 입력값에 따르는 특정한 출력값이 나오는 '보이지 않는 마술상자'처럼 비유되는데, 유치해 보이는 이 관점이 외려 함수의 정의와 더욱 근접한다. 당장 函數라는 한자표기부터 뜯어보면 函자는 다름아닌 상자 함. 무슨무슨 함 할 때의 함 자가 바로 이 함(函)자다. 이는 심지어 2번 항목의 함수와도 이어진다!

1211.png
[PNG image (Unknown)]

바로 이런 것. 이걸 수식으로 표현하면, $ y = x + 4 $ 되시겠다. 괜히 쉬운 것도 식으로 표현하니 어려워 보인다

1.2. 함수의 전사와 단사

  • f(a)=f(b) ⇒ a=b : 단사(injective) 또는 일대일(one-to-one)이라 하고 일대일인 함수를 단사함수(injection) 또는 일대일함수(one-to-one function)이라 한다.
    함수가 일대일 함수임을 보일때는 정의를 사용하기도 하지만, 명제의 대우로 a≠b ⇒ f(a)≠f(b)를 사용하기도 한다.
  • ∀y∈Y, ∃x∈X, f(x)=y. 즉 치역과 공역이 같을 때를 전사(surjective) 또는 (X에서) Y 위로(onto)의 함수라 한다. 전사인 함수를 전사함수(surjection)이라 한다.
  • f:X→Y가 전사이고 단사일때 f를 전단사(bijective)라 한다. 전단사인 함수를 전단사함수(bijection) 또는 일대일 대응(one-to-one correspondence)라 한다. one-to-one & onto라고도 많이 사용한다.

아이고 맙소사

1.3. 함수의 합성, 항등함수, 역함수

간혹 함수를 f(g(x))처럼 겹쳐 써야 할 때가 있는데 여러 함수를 겹쳐 쓰다 보면 헷갈리기 때문에 이를 단순화시키는 표기가 생겼는데 바로 합성함수라는 것이다. 대개 f(g(x)) = f∘g(x)로 쓴다. 계산 과정상 맨 오른쪽 함수부터 계산 과정이 진행된다.

함수의 합성은 기본적으로 f∘g ≠ g∘f, 즉 교환법칙이 성립하지 않는다. 쉽게 말하자면 컵에 인스턴트 커피, 뜨거운 물, 얼음 순으로 넣는 것과 얼음, 뜨거운 물, 인스턴트 커피 순으로 넣는 것의 결과물이 다른 것과 같다. 굳이 수학적인 방법으로 예를 든다면, 다음과 같다.
tan∘sin(1) = tan(sin(1)) = 1.1189396031849523172913330821457...
sin∘tan(1) = sin(tan(1)) = 0.99991037400520362471643104847616...
특별한 이유가 없다면 교환법칙은 성립하지 않는 것이 당연하므로, 주의하는 것이 좋다. 물론 결합법칙 f∘(g∘h)(x) = (f∘g)∘h(x) 은 자연스럽게 성립한다.

동일 함수가 합성됐을 경우 f∘f(x) = f2(x)로 정의한다. 지수 꼴의 숫자는 합성한 횟수이다. 단, 삼각함수에는 적용되지 않는다.

함수 f:X->X가 원소를 같은 그대로 대응시키면, 즉 모든 x에 대해 f(x)=x라면, f를 항등함수라고 한다. 표기법은 iX , IX , 1X , idX 등으로 다양하다. 함수의 합성에서 항등함수는 항등원과 비슷한 역할을 한다. 즉 f∘i=f, i∘f=f. 다만 주의할 점은 모든 x에 대해 f(x)=x이기만 하면 항등함수가 될 수 없고, 반드시 정의역과 공역이 같아야 한다는 것이다.

함수 f:X->Y가 전단사이면 그 역함수 f-1 :Y->X를 생각할 수 있는데, 이는 Y의 원소 y에 대해 f(x)=y인 유일하게 존재하는 x를 대응시키는 것이다. 다시 말해서 f(x)=y ⇔ f-1 (y)=x. 함수의 정의에 비추어 보면 이는 f가 전단사일 때밖에 생각할 수 없다는 것을 알 수 있다. 만약 g가 f의 역함수라면 f∘g는 X에서의 항등함수이고 g∘f는 Y에서의 항등함수가 되고, 이는 함수의 합성에선 역함수가 역원과 비슷한 역할을 한다는 것을 말해준다. 단 f∘g와 g∘f가 다르다는 것은 주의해야 한다. 둘 다 항등함수라지만 전자는 X에서, 후자는 Y에서의 항등함수이다.

1.4. 몰라도 되는 함수의 역사

위의 함수의 정의는 깔끔하지만, 보통 우리가 생각하는 대응관계의 개념과는 꽤 동떨어져 보인다는 것이 의아하게 느껴질 것이다. 이를 이해하기 위해서는 함수가 나타난 역사적 문맥을 살펴보아야 한다.

초창기의 함수는 하나의 대상 y가 다른 대상 x와 어떻게 관계하는지의 개념이었다. 대표적인 예로 갈릴레이가 낙하법칙을 표현할 때 비례하는 관계를 생각한 것이 있겠다. 미적분학이 태동하면서 함수의 개념은 "변수 x의 변화에 따른 y의 변화"로 자연스럽게 전환되었고, 이 때 함수(function)라는 용어가 라이프니츠(Leibniz, G.W.)에 의해 처음 쓰이게 되었다. 한편 데카르트의 해석기하학의 관점에선 도형은 대수식으로 생각할 수 있었고, 이 미적분학의 운동과 변화의 개념도 자연히 대수학으로 설명되었다. 이것이 극단에 이르러 근대적 대수학의 이론이 상당히 발전한 오일러(Euler, L.) 대에는 "식으로 나타낼 수 있는 대상"들을 함수로 생각하게 되었다. 기호 f(x)도 이 때 오일러가 고안한 것이다.

물론 이 관념은 수학이 더욱 발전하면서 자연스레 맹공을 받게 된다. 푸리에(Fourier, J.)의 삼각함수의 무한급수 이론 - 소위 말하는 푸리에 해석 - 으로 미분이 불가능한 식이 처음 등장하였고, 오일러마저도 정말 개념없이 써왔던 극한과 연속의 개념을 코시(Cauchy, L.)가 입실론-델타로서 고찰하게 되었다. 이리하여 이런저런 과정을 통해 "추상적 대응으로서의 함수의 현대적 정의", 즉 1.1의 정의가 디리클레(Dirichlet, P.G.L.)에 의해 고안되었다. 그는 다음의 디리클레 함수
D(x)=(x가 무리수면 0, 유리수면 1)
라는 지금 보면 별거 아니지만 그 당시에는 충격이었던 함수를 꺼내들었다. 해석학을 배운 위키러라면, 이 함수는 어디에서도 연속이 아니라는 것을 알 수 있을 것이다. 하지만 이 함수를 표현하는 다음과 같은 식이 존재한다(...)
D(x) = limm->∞ limn->∞ cos2n (m!πx)
이는 위에서 생각한 두 가지 함수의 개념이 엄밀한 수학에는 걸림돌이 된다는 것을 의미하였고, 자연히 함수에 대한 엄밀한 정의가 요구되었다. 이렇게 해서 등장한 디리클레의 정의는 현대까지 매우 유용하게 쓰이게 되고, 미적분학은 이 함수의 정의를 바탕으로 다시 엄밀하게 해석학이란 이름으로 다시 태어나게 된다. 여기까지가 대략 함수의 일반적 정의가 등장한 배경이라고 볼 수 있겠다.

순수수학 내부에선 이 디리클레의 정의는 현대까지 크게 바뀌지 않았고, 다만 집합의 개념이 엄밀하게 정립될 때 약간의 변경이 있었다. 공리적 집합론에선 함수의 정의역과 공역이 반드시 '집합' - 즉 (axiomatic) set - 이어야 된다는 점이 강조되고, 이 때 함수를 '집합'으로서 생각한다. 함수의 집합론적 정의는 집합 X와 Y에 대해 (정의역 X, 공역 Y, 대응관계 f)의 순서쌍으로, f는 곱집합 X*Y의 부분집합 중 위에 서술한 함수의 조건을 만족하는 것들로 생각된다. 물론 우리가 생각하는 대부분의 대상들은 집합이므로 대부분의 사람들은 이 문제를 생각하지 않는다.

다만 함수에 대한 관념은 그 이후에도 계속 바뀌어 왔다. 집합과 함수의 관계를 무지막지하게 일반화한 범주론(category theory)의 사상(morphism)의 개념은 함수에 대해 정말 특수한 시각을 제공했고, '마술상자'로서의 함수 개념은 2번 항목의 함수 개념과 자연스럽게 이어져서 계산가능성(computability)의 이론을 등장시키게 되었다. 같은 수학자라도 함수 하면 떠올리는 것은 분야마다 천차만별일 것이다.

1.5. 관련 항목

2. 프로그래밍에서의 함수

프로그래밍에서의 함수는 프로그램 소스 코드에서 일정한 동작을 수행하는 코드(들)[4]을 말한다. 이때 프로그램이 동작할 때 함수의 호출 과정은 다음과 같다.
  • 코드 상에서 함수가 호출된다. 이때 변수를 넘겨주기도 하는데 이를 매개변수 또는 인수라고 한다.
  • 호출된 함수의 코드가 동작한다.
  • 함수의 동작이 끝나면 함수를 종료하고 경우에 따라 반환값을 코드에 반환한다.

이 함수는 크게 내장 함수와 사용자 정의 함수로 나뉜다. 내장 함수는 프로그래밍 언어 차원에서 이미 정의되어 있는 함수로, 별도로 함수를 만들 필요 없이 형식에 맞춰 불러 쓰기만 하면 된다. 언어 레퍼런스를 보면 상당히 많은 내장 함수가 제공되는 것을 알 수 있다.

사용자 정의 함수는 프로그래머가 만들어 쓰는 함수로, 코드의 어딘가에 미리 정의해 둬야 불러쓸 수 있다.

2.1. 함수의 장점

함수를 이용하면 불필요하거나 여러 번 중복되는 코드를 함수를 호출하는 식으로 간단하게 정리할 수 있다. 또한 프로그램을 여러 함수로 분리하여 프로그래밍에서 더욱 쉬워지기 때문에 현재 대다수의 프로그래밍 언어는 함수를 지원한다.

2.2. 함수 호출시 오버헤드

함수를 불러올 때, 호출 뒤 귀환할 주소와 현재의 상태를 담고 있는 각종 레지스터를 어딘가에 저장해야한다. 이런 정보들을 저장하는 장소를 보통 호출 스택(call stack) 또는 런 스택(run stack)이라고 한다. 함수를 콜 하기 전에 이런 정보를 저장하는 작업이 필요하므로 약간의 오버헤드가 생긴다. 따라서 프로그램의 속도를 골수로 뽑아내야 하는 시스템 프로그램에는 필요 이상의 함수 콜을 자제하고, 함수 스타일의 매크로를 많이 이용하곤 했다. 또한, 과거에는 컴파일을 하고도 그걸 도로 디스어셈블해서 코드를 손으로 최적화하는 삽질이 많았으나 대부분 옛날 얘기고, 요즘은 왠만한 함수 호출 부하따윈 씹어먹을만큼 하드웨어가 발전했고, 정 부하가 될 만한 부분은 컴파일러가 자동으로 함수 호출 코드를 함수 내용으로 바꿔주는(인라이닝[5]) 등의 최적화 테크닉을 컴파일러가 자동으로 해주므로 함수를 멀리하고 매크로를 가까이 할 필요성은 사실상 사라졌다. 그러니깐 최적화한답시고 디스어셈블질하지 말고 병목이나 제거하자

재귀함수를 짤 경우 호출 스택의 용량에는 한계가 있기 때문에 그 용량을 초과해서 재귀 호출하면 스택 오버플로우가 발생할 수 있다. 단 일반 함수와 달리 함수를 후 값을 반환하는 대신 주어진 환경에서 메모리 주소를 점프하며 함수만 갈아끼우는 끝재귀 최적화(Tail-call optimization)가 지원되는 컴파일러는 재귀 스타일로 짜더라도 스택 오버플로우를 방지할 수 있다. 물론 끝재귀 최적화가 가능하게 짜 줘야 한다[6]. 현재 주요 컴파일러(gcc, clang/llvm, vc)에는 모두 포함되어 있는 기능이다. 안습하게도 Java에선 지원하지 않는다. 대신 다른 JVM기반 언어인 Scala나 Clojure에선 각각 끝재귀 최적화 가능하게 코딩하면 컴파일 시 루프로 변환하거나 명시적으로 재귀시켜 컴파일 시 루프로 변환시킬 수 있다.

2.3. 수학 함수와의 관계


수학에서의 함수와 프로그래밍에서의 함수는 대동소이해 보이지만 크게 다르다. 특정한 값을 입력하여 특정한 값을 출력하는 메커니즘 자체는 같지만, 프로그래밍에서의 함수는 내적으로 그 입력값을 어떻게 다루어 출력값을 내는지도 보는 반면, 수학에서의 함수는 순수하게 입력값과 출력값만을 본다. 전자를 Intensionality 라 하고, 후자를 Extensionality 라 하는데[7], 이로인해 깊은 부분에서 큰 차이가 발생하는 경우가 많다.

둘째로 정의역과 공역이 모든 집합이 다 허용되는 수학 함수와는 달리 프로그래밍에서는 이산적인 집합만 허용된다. 이는 알고리듬적인 집합(recursively enumerable set)만 다룰 수 있는 컴퓨터 자료 구조의 한계, 나아가서는 알고리듬의 수학적 모델 자체의 한계로 인해 발생한 것.

또한 수학 함수와는 달리 하나에 입력에 여러가지 출력이 대응되어도 상관없다. 난수가 가장 좋은 예로, 이는 함수 내부에 사이드이펙트를 연출가능한 변수가 존재할 수 있기 때문이다.

여담이지만, 프로그래밍에서의 함수를 수학에서의 함수처럼 에뮬레이션하여(이 경우에도 Intensionality 와 알고리듬적인 자료구조만을 사용하는것은 동일하다. 사이드 이펙트만을 제한한것.)와 프로그래밍 하는 순수 함수형 프로그래밍 언어 역시 존재한다.

대부분 전사나 단사를 따지지 않아도 되지만, 이걸 따져야 하는 경우도 있다. 튜링 테스트의 대표격인 CAPTCHA와, JPEG의 양자화(또는 계수화)에는 역함수가 존재하지 않기 때문에(단사가 아니기 때문에) 완벽하게 복원할 방법이 없으며, 이 때문에 아직 튜링 테스트를 통과한 기계가 없고, 앞으로도 당연히 없을 것이다.. 비손실 압축과 양방향 암호 알고리즘은 해당 함수가 전단사여야만 유효하며,[8] 굳이 단사일 필요가 없는 단방향 암호 알고리즘 마저도 단사가 아닌 경우(충돌)를 최소화해야 한다.

3. 걸그룹 f(x)의 별명

이유야 뭐 보다시피 걸그룹 이름이 f(x)이기 때문. 항목 참조.
미분하면 f'(x) 적분하면 F(x)+C

4. 소금기가 많은 짠물. 鹹水

쉽게 말하면 소금물. 바다물을 함수라 하기도 한다.
소금을 만들 때는 바닷물을 염전에서 모아 농축시킨 짠물을 말한다.

5. 자일대우버스 FX시리즈의 별명


FX라는 이름때문에 별명이 붙어졌다. 그리고 3번 항목보다 일찍 붙여젔다. SM의 상표권 침해

자세한 내용은 자일대우버스 FX 항목 참조.

6. 군함의 앞부분. 艦首


말 그대로 배의 앞부분을 말한다. 보통 별 시설은 없지만 물의 저항을 줄여주는 형태를 가지고 있어서 강한 폭발 등으로 부러지면 함선이 매우 느려진다. 함이라는 말 자체가 군함이라는 의미가 있어서 일반 선박의 경우 선수라고 부른다.
----
  • [1] 알파벳 F는 function(함수)의 첫글자에서 나왔다. 이 바닥이 다 그렇듯이 여러개의 함수를 나타낼 때에는 알파벳 나열하듯 f, g, h, ...등의 알파벳으로 함수를 나타낸다. 물론 이런 것만 쓰이는게 아니라 a(x)라거나 a(b), x(f) 등등의 형태도 함수기 때문에 낚이기 않게 주의하자.
  • [2] 읽기 편하라고 에프엑스라고 부르지만 영어권에서는 "function of x", 짧게는 "f of x"로 읽는다. 즉 x의 function이라는 말 그대로의 의미. fx로는 읽지 않는다. 이런 것 비슷한 것 중에 지수함수 읽는 법이 있는데, a^x 는 "a to the power of x", 줄여서 "a to the x" 라고 읽는다.
  • [3] 위 함수가 실수에서 정의되었으면 전사(surjective)가 아니지만, 복소수에서 정의되었으면 전사이다. 만약 이 함수가 음이 아닌 실수에서 음이 아닌 실수로 가는 함수라면 전단사일 것이다.
  • [4] 보통은 코드가 여럿인 경우만 생각하지만, C언어의 매크로 함수나 인라인 함수, OOP의 접근자(accessor) 등의 경우 코드가 하나인 경우도 있다.
  • [5] 언어에 따라 inline 키워드를 붙여 마음대로 인라인 할 수도 있다. 물론 재귀함수같은 건 키워드 붙여도 안된다.
  • [6] 함수 호출 후 아무것도 하지 않고 바로 그 값을 리턴할 때.
  • [7] 집합론의 제일공리가 Extensionality 이다.
  • [8] 암호 알고리즘이 전단사가 아니라면 원하지 않는 개인키로 암호를 해독하는 등, 암호 체계 자체가 쓸모 없어진다.