Min and max

Min and max (최솟값과 최댓값)

정해진 개수의 인자들 중에서 가장 작은 값, 또는 가장 큰 값을 구하고 싶을 때가 많죠. 예를 들어 세 숫자 중 최댓값을 꺼내야 한다면, 매번 비교를 직접 쓰느라 코드가 지저분해지기 쉬운데요. Go에는 이걸 그냥 함수로 해결해 주는 내장 함수가 있어요. 바로 minmax입니다. 고정된 개수의 인자(argument) 중에서 가장 작은, 혹은 각각 가장 큰 값을 계산해 주는 내장 함수예요.

출처: Go Specification

본문

내장 함수 minmax정렬 가능한 타입(ordered types)의 인자들이 일정한 개수 있을 때, 그중에서 각각 가장 작은 값과 가장 큰 값을 계산해요. 인자는 최소한 하나는 있어야 해요 [Go 1.21].

연산자(operator)와 똑같은 타입 규칙이 적용돼요. 즉 정렬 가능한 인자 xy에 대해 min(x, y)가 유효하려면 x + y가 유효해야 하고, min(x, y)의 타입은 x + y의 타입과 같아요 (max도 마찬가지예요). 모든 인자가 상수라면 결과도 상수예요.

var x, y int
m := min(x)                 // m == x
m := min(x, y)              // m is the smaller of x and y
m := max(x, y, 10)          // m is the larger of x and y but at least 10
c := max(1, 2.0, 10)        // c == 10.0 (floating-point kind)
f := max(0, float32(x))     // type of f is float32
var s []string
_ = min(s...)               // invalid: slice arguments are not permitted
t := max("", "foo", "bar")  // t == "foo" (string kind)

숫자 인자의 경우, 모든 NaN이 서로 같다고 가정하면 minmax는 교환 법칙(commutative)과 결합 법칙(associative)을 만족해요.

min(x, y)    == min(y, x)
min(x, y, z) == min(min(x, y), z) == min(x, min(y, z))

부동소수점(floating-point) 인자의 경우, 음의 영(negative zero), NaN, 무한대(infinity)에 대해서는 다음 규칙이 적용돼요.

   x        y    min(x, y)    max(x, y)

  -0.0    0.0         -0.0          0.0    // negative zero is smaller than (non-negative) zero
  -Inf      y         -Inf            y    // negative infinity is smaller than any other number
  +Inf      y            y         +Inf    // positive infinity is larger than any other number
   NaN      y          NaN          NaN    // if any argument is a NaN, the result is a NaN

문자열 인자의 경우, min의 결과는 바이트 단위로 어휘 비교(lexically byte-wise)했을 때 가장 작은 값(또는 max는 가장 큰 값)을 가진 첫 번째 인자가 돼요.

min(x, y)    == if x <= y then x else y
min(x, y, z) == min(min(x, y), z)

더 알아보기

  • Go 1.21에서 내장 min/max가 도입됐어요. 그 전에는 이런 비교를 직접 구현하거나 외부 헬퍼에 의존해야 했죠.
  • 부동소수점에서는 -0.00.0을 서로 다르게 취급하고, NaN이 하나라도 섞이면 결과가 NaN이 된다는 점을 기억해 두면 좋아요.
  • min/max의 타입 규칙이 일반 연산자와 같다는 점은, 타입 추론이 어떻게 흘러가는지 이해할 때 유용한 단서예요.