산술 연산자

산술 연산자

Free Pascal에서는 +, -, *, /, ** 같은 산술 연산자도 직접 오버로드해서, 자신의 타입에 맞는 연산 동작을 정의할 수 있어요.

출처: 문서

본문

산술 연산자는 이항 연산자(binary operator)의 동작을 정의해요. 가능한 연산은 다음과 같습니다.

  • 곱셈(multiplication) — 두 타입을 곱하려면 * 곱셈 연산자를 오버로드해야 해요.
  • 나눗셈(division) — 두 타입을 나누려면 / 나눗셈 연산자를 오버로드해야 해요.
  • 덧셈(addition) — 두 타입을 더하려면 + 덧셈 연산자를 오버로드해야 해요. 주의할 점은, +는 배열 연결을 위한 내부 컴파일러 연산이므로 동적 배열(dynamic array)에는 사용할 수 없어요. (modeswitch ARRAYOPERATORS 참고)
  • 뺄셈(subtraction) — 두 타입을 빼려면 - 뺄셈 연산자를 오버로드해야 해요.
  • 거듭제곱(exponentiation) — 두 타입을 거듭제곱하려면 ** 지수 연산자를 오버로드해야 해요.
  • 단항 마이너스(Unary minus) — 뒤에 오는 인자의 음수를 취할 때 사용돼요.
  • 대칭차(Symmetric Difference) — 두 구조체의 대칭차를 구하려면 >< 연산자를 오버로드해야 해요.

산술 연산자 정의는 두 개의 매개변수를 받아요. 단항 마이너스만 예외로 하나의 매개변수를 받죠. 첫 번째 매개변수는 연산자 왼쪽에 오는 타입이어야 하고, 두 번째 매개변수는 연산자 오른쪽에 오는 타입이어야 합니다. 결과 타입은 산술 연산을 수행한 뒤 나오는 타입과 일치해야 해요.

다음 표현식을 컴파일하려면

var
  R : real;
  C,Z : complex;
begin
  C:=R*Z;
end;

곱셈 연산자를 이렇게 정의해야 합니다.

Operator * (r : real; z1 : complex) z : complex;
begin
  z.re := z1.re * r;
  z.im := z1.im * r;
end;

여기서 첫 번째 연산자는 real, 두 번째는 complex예요. 결과 타입은 complex죠.

교환 법칙은 적용되지 않아요

실수와 복소수의 곱셈·덧셈은 교환적(commutative) 연산이지만, 컴파일러는 이 사실을 알지 못합니다. 그래서 realcomplex 사이의 곱셈을 정의했더라도, complexreal 순서로 만나면 그 정의를 사용하지 않아요. 두 방향 모두 정의해 주어야 합니다.

그래서 위 곱셈 정의만 있으면, 컴파일러는 다음 문장을 받아들이지 않아요.

var
  R : real;
  C,Z : complex;
begin
  C:=Z*R;
end;

ZR의 타입이 연산자 정의에 있는 타입 순서와 맞지 않기 때문입니다. 이렇게 동작하는 이유는 곱셈이 항상 교환적이지는 않기 때문이에요. 예를 들어 (n,m) 행렬과 (m,n) 행렬의 곱은 (n,n) 행렬이 되지만, (m,n)(n,m) 순서로 곱하면 (m,m) 행렬이 되어 항상 같지 않을 수 있어요.

더 알아보기