mathop — 수학 연산자를 Tcl 명령으로 쓰기

mathop — 수학 연산자를 Tcl 명령으로 쓰기

expr 안에서만 쓰던 +, *, == 같은 연산자를, 밖에서도 명령처럼 직접 쓰고 싶을 때가 있어요. ::tcl::mathop 네임스페이스의 명령들이 바로 그 역할을 해서, 수식을 분리해서 계산하거나 리스트의 값을 연속으로 비교할 때 유용합니다.

출처: Tcl Commands — mathop

본문

package require Tcl 8.5
::tcl::mathop::! number
::tcl::mathop::~ number
::tcl::mathop::+ ?number ...?
::tcl::mathop::- number ?number ...?
::tcl::mathop::* ?number ...?
::tcl::mathop::/ number ?number ...?
::tcl::mathop::% number number
::tcl::mathop::** ?number ...?
::tcl::mathop::& ?number ...?
::tcl::mathop::| ?number ...?
::tcl::mathop::^ ?number ...?
::tcl::mathop::<< number number
::tcl::mathop::>> number number
::tcl::mathop::== ?arg ...?
::tcl::mathop::!= arg arg
::tcl::mathop::< ?arg ...?
::tcl::mathop::<= ?arg ...?
::tcl::mathop::>= ?arg ...?
::tcl::mathop::> ?arg ...?
::tcl::mathop::eq ?arg ...?
::tcl::mathop::ne arg arg
::tcl::mathop::in arg list
::tcl::mathop::ni arg list

::tcl::mathop 네임스페이스의 명령들은 expr 명령이 지원하는 것과 동일한 연산 집합을 구현해요. 모두 네임스페이스에서 내보내지지만(export), 기본적으로 다른 네임스페이스로 임포트되지는 않아요. 네임스페이스의 명령을 이름 바꾸기·재구현·삭제해도 expr 명령의 동작은 바뀌지 않고, ::tcl::mathop 네임스페이스에 새 명령을 정의해도 마찬가지예요.

지원되는 연산자 명령: ~ ! + - * / % ** & | ^ >> << == eq != ne < <= > >= in ni

수학 연산자

! boolean boolean의 불리언 부정을 돌려줘요. boolean은 숫자 값이거나 다른 형태의 불리언 값일 수 있어요(인수가 거짓이거나 0이면 참을, 참이거나 0이 아니면 거짓을 돌려줘요).

+ ?number ...? 인수가 몇 개든 그 합을 돌려줘요. 각 number 인수는 어떤 숫자 값이든 될 수 있어요. 인수가 없으면 결과는 0(덧셈의 항등원)이에요.

- number ?number ...? 인수가 하나뿐이면 그 숫자 값의 부정을 돌려줘요. 그렇지 않으면 첫 번째 숫자 값에서 이후의 모든 숫자 값을 뺀 결과를 돌려줘요. 모든 number 인수는 숫자 값이어야 해요. 인수는 최소 하나는 주어져야 해요.

* ?number ...? 인수가 몇 개든 그 곱을 돌려줘요. 각 number는 어떤 숫자 값이든 될 수 있어요. 인수가 없으면 결과는 1(곱셈의 항등원)이에요.

/ number ?number ...? 인수가 하나뿐이면 그 숫자 값의 역수(즉 1.0을 그 값으로 나눈 값)를 돌려줘요. 그렇지 않으면 첫 번째 숫자 인수를 이후의 모든 숫자 인수로 나눈 결과를 돌려줘요. 모든 number 인수는 숫자 값이어야 해요. 인수는 최소 하나 주어져야 해요.

인수 목록의 앞쪽 값들이 정수이면, 그 처음 단계들에는 정수 나눗셈이 사용돼요(즉 중간 결과가 마치 floorint 함수를 그 순서대로 적용한 것처럼 돼요). 연산의 모든 값이 정수이면 결과도 정수예요.

% number number 첫 번째 인수를 두 번째 인수에 대한 적분 나눗셈의 나머지(integral modulus)로 돌려줘요. 각 number는 정수 값이어야 해요. 결과의 부호는 두 번째 숫자의 부호와 같고, 두 번째 숫자는 0이 아니어야 해요.

Tcl은 음수에 대해서도 이 연산을 정확히 정의하므로, 다음 명령은 참 값을 돌려줘요(명확성을 위해 네임스페이스는 생략):

== [* [/ x y] y] [- x [% x y]]

** ?number ...? 각 값을, 뒤따르는 인수들을 재귀적으로 처리한 결과의 거듭제곱으로 올린 결과를 돌려줘요. 즉 ** 2 3 4** 2 [** 3 4]와 같아요. 각 number는 어떤 숫자 값이든 될 수 있지만, 첫 번째가 음수이면 두 번째 숫자는 분수여서는 안 돼요. 첫 번째 숫자가 1보다 큰 정수일 때 Tcl이 처리할 수 있는 최대 지수 값은 268435455예요. 인수가 없으면 결과는 1이고, 인수가 하나뿐이면 결과는 그 인수예요. 결과가 정수 값을 갖는 것은 모든 인수가 정수 값일 때뿐이에요.

비교 연산자

(대부분 숫자 인수를 우선적으로 다루는) 비교 연산자 명령의 동작은 다음과 같아요.

== ?arg ...? 각 인수가 양옆의 인수와 expr== 연산자 의미로(즉 가능하면 숫자 비교, 그렇지 않으면 정확한 문자열 비교) 같은지 돌려줘요. 인수가 두 개보다 적으면 이 연산은 항상 참을 돌려줘요.

eq ?arg ...? 각 인수가 양옆의 인수와 정확한 문자열 비교로 같은지 돌려줘요. 인수가 두 개보다 적으면 항상 참을 돌려줘요.

!= arg arg 두 인수가 서로 같지 않은지 expr!= 연산자 의미로(가능하면 숫자 비교, 그렇지 않으면 정확한 문자열 비교) 돌려줘요.

ne arg arg 두 인수가 정확한 문자열 비교로 같지 않은지 돌려줘요.

< ?arg ...? 인수가 몇 개든 순서가 맞는지, 즉 첫 번째 이후 각 인수가 바로 앞 인수보다 엄격히 커야 하는지 돌려줘요. 비교는 숫자 값을 우선 수행하고, 그렇지 않으면 UNICODE 문자열 비교로 수행해요. 인수가 두 개보다 적으면 항상 참을 돌려줘요. 인수가 숫자인데 문자열로 비교해야 한다면 string compare 명령을 대신 써야 해요.

<= ?arg ...? 인수가 몇 개든 순서가 맞는지, 즉 첫 번째 이후 각 인수가 바로 앞 인수보다 같거나 커야 하는지 돌려줘요. 비교는 숫자 값을 우선 수행하고, 그렇지 않으면 UNICODE 문자열 비교로 수행해요. 인수가 두 개보다 적으면 항상 참을 돌려줘요. 인수가 숫자인데 문자열로 비교해야 한다면 string compare 명령을 대신 써야 해요.

> ?arg ...? 인수가 몇 개든 순서가 맞는지, 즉 첫 번째 이후 각 인수가 바로 앞 인수보다 엄격히 작아야 하는지 돌려줘요. 비교는 숫자 값을 우선 수행하고, 그렇지 않으면 UNICODE 문자열 비교로 수행해요. 인수가 두 개보다 적으면 항상 참을 돌려줘요. 인수가 숫자인데 문자열로 비교해야 한다면 string compare 명령을 대신 써야 해요.

>= ?arg ...? 인수가 몇 개든 순서가 맞는지, 즉 첫 번째 이후 각 인수가 바로 앞 인수보다 같거나 작아야 하는지 돌려줘요. 비교는 숫자 값을 우선 수행하고, 그렇지 않으면 UNICODE 문자열 비교로 수행해요. 인수가 두 개보다 적으면 항상 참을 돌려줘요. 인수가 숫자인데 문자열로 비교해야 한다면 string compare 명령을 대신 써야 해요.

비트 연산자

(모두 정수 인수에만 동작하는) 비트 연산자 명령의 동작은 다음과 같아요.

~ number number의 비트 단위 부정을 돌려줘요. number는 크기와 무관한 정수일 수 있어요. 이 연산의 결과는 항상 입력 숫자와 반대 부호를 갖는다는 점을 기억하세요.

& ?number ...? 인수가 몇 개든 각각의 비트 단위 AND를 돌려줘요. 각 number는 정수 값이어야 해요. 인수가 없으면 결과는 마이너스 1이에요.

| ?number ...? 인수가 몇 개든 각각의 비트 단위 OR를 돌려줘요. 각 number는 정수 값이어야 해요. 인수가 없으면 결과는 0이에요.

^ ?number ...? 인수가 몇 개든 각각의 비트 단위 XOR을 돌려줘요. 각 number는 정수 값이어야 해요. 인수가 없으면 결과는 0이에요.

<< number number 첫 번째 인수를 두 번째 인수에 지정된 비트 수만큼 왼쪽으로 비트 시프트한 결과를 돌려줘요. 각 number는 정수 값이어야 해요.

>> number number 첫 번째 인수를 두 번째 인수에 지정된 비트 수만큼 오른쪽으로 비트 시프트한 결과를 돌려줘요. 각 number는 정수 값이어야 해요.

리스트 연산자

리스트 지향 연산자 명령의 동작은 다음과 같아요.

in arg listarg가 리스트 list에 존재하는지(요소의 정확한 문자열 비교 기준) 돌려줘요.

ni arg listarg가 리스트 list에 존재하지 않는지(요소의 정확한 문자열 비교 기준) 돌려줘요.

예제

연산자를 쓰는 가장 간단한 방법은 namespace path로 명령을 사용 가능하게 만드는 경우가 많아요. 이렇게 하면 현재 네임스페이스가 정의하는 명령 집합에는 영향을 주지 않는 장점이 있어요.

namespace path {::tcl::mathop ::tcl::mathfunc}

# Compute the sum of some numbers
set sum [+ 1 2 3]

# Compute the average of a list
set list {1 2 3 4 5 6}
set mean [/ [+ {*}$list] [double [llength $list]]]

# Test for list membership
set gotIt [in 3 $list]

# Test to see if a value is within some defined range
set inRange [<= 1 $x 5]

# Test to see if a list is sorted
set sorted [<= {*}$list]

더 알아보기

  • expr — 수식 평가 명령
  • mathfunc — 수학 함수
  • namespace — 네임스페이스 관리