8-1-마.절대값 함수

절대값 함수는 인수의 부호를 강제로 양수로 바꾼다. 즉 3은 그냥 3으로 두고 -3은 3으로 바꾸는 것이다. 인수의 타입에 따라 3가지 함수가 준비되어 있다. 이외에 복소수 타입에 대한 절대값 함수도 있으나 여기서는 다루지 않기로 한다.

 

int abs(int n);

long labs(long n);

double fabs(double x);

 

위에서부터 순서대로 정수형, long형, 실수형에 대한 절대값을 구한다. 16비트 환경에서는 int형과 long형의 길이가 다르므로 함수가 따로 준비되어 있지만 32비트 환경에서는 int가 long과 같기 때문에 abs와 labs 함수는 동일하다고 할 수 있다. 굳이 예제가 필요하지는 않겠지만 그래도 없으면 섭섭하므로 확인만 해 보도록 하자.

 

: abs

#include <Turboc.h>

#include <math.h>

 

void main(void)

{

     int i=3, j=-3;

 

     printf("%d의 절대값 = %d\n",i,abs(i));

     printf("%d의 절대값 = %d\n",j,abs(j));

}

 

3과 -3에 대한 절대값을 구해 출력해 보았다.

 

3의 절대값 = 3

-3의 절대값 = 3

 

만약 i, j가 실수형 변수라면 abs 함수 대신 fabs 함수를 사용해야 할 것이다. 타입에 따라 이런 함수를 쓰는 대신 삼항 조건 연산자를 사용할 수도 있다. (a>0) ? a:-a연산식이 절대값을 구하는 식인데 a가 양수이면 a를 리턴하고 a가 음수이면 - 부호 연산자를 사용하여 부호를 반대로 뒤집어 주었다. 연산자는 모든 수치형 타입에 공통적으로 쓸 수 있으므로 타입에 따라 다른 함수를 호출하는 것보다는 오히려 삼항 조건 연산자를 사용하는 것이 속도상으로 보나 프로그램 크기로 보나 유리하다. 자주 사용한다면 다음과 같은 매크로를 만들어 쓰는 것도 좋다.

 

#define MyAbs(a) (((a)>0) ? (a):-(a)))

 

절대값의 수학적 정의가 간단하기 때문에 절대값 함수는 아주 이해하기 쉽다. 너무 쉽다 보니 이런 함수들이 왜 필요한가 싶겠지만 이 간단한 함수들도 응용하기에 따라서는 엄청난 위력을 발휘할 때가 있다. 몇 가지 예를 들어 보자. 만약 a가 -10이거나 10일 때 어떤 동작을 하고 싶다고 하자. 이 경우 조건문을 다음과 같이 작성할 것이다.

 

if ((a==10) || (a==-10)) { ... }

 

a를 10, -10과 각각 비교해 보고 두 비교 연산문을 || 논리 연산자로 연결하면 된다. 그러나 이 방법보다는 if (abs(a)==10) { ... } 이라고 하는 편이 훨씬 더 간단하다. 비교 연산을 하기 전에 부호를 제거해 버리고 양수 10과 한 번만 비교하면 되는 것이다. 비교할 두 수의 절대값이 같다는 것을 이용했는데 절대값이 다른 경우에도 이런 기법을 쓸 수 있다. 이번에는 a가 10이거나 20인 경우의 조건문을 만들어 보자. 다음 두 조건문이 같다는 것을 알 수 있다.

 

if ((a==10) || (a==20)) { ... }

if (abs(15-a) == 5) { ... }

 

비교될 두 수의 중점과 비교할 수의 차에 대한 절대값을 한 번만 비교하면 된다. abs 함수가 절대값을 구하므로 abs(15-a)는 abs(a-15)로 써도 결과는 동일하다. 이 예와 같이 단순 변수와 상수를 비교할 때는 큰 차이가 없지만 함수 호출 결과를 비교할 때는 함수를 두 번 호출할 것을 한 번만 호출해도 되는 큰 차이가 발생한다. 이번에는 범위를 점검하는 조건문을 만들어 보자. a가 10~50사이에 있는지 검사하고자 할 때도 abs 함수를 사용할 수 있다.

 

if ((a>10) && (a<50) { ... }

if (abs(a-30) < 20) { ... }

 

어떤 값이 특정 범위에 있는지를 절대값으로 검사하는 이 방식은 아주 일반적이며 정형화되어 있는 알고리즘이다. 우리가 이 방법을 직접 사용하지 않는다 하더라도 지능적인 컴파일러는 범위를 비교할 때 이 알고리즘을 적극적으로 활용한다. 두 개의 조건문을 따로 검사하고 && 연산하는 것보다는 절대값을 하나의 값과 비교하는 것이 속도상 훨씬 더 유리하기 때문이다.

지금 여기서 abs 함수를 응용해서 범위 점검을 쉽게 하는 방법이 있다는 것을 소개하고자 하는 것은 아니다. abs같은 아메바 수준의 간단한 함수라도 적절한 위치에 제대로 응용하면 몇 백줄의 코드를 대신하는 역할을 할 수도 있다는 것을 강조하고 싶다. 그러니 지금 당장은 사소해 보이고 별 것 아닌 것 같이 생각되더라도 가벼이 보지 말고 최소한 이런 것도 있었다는 것은 알아 두도록 하자.