@divTrunc — 정수 나눗셈, 0을 향해 버리기

@divTrunc — 정수 나눗셈, 0을 향해 버리기

안녕하세요! 오늘은 정수 나눗셈할 때 소수점을 0을 향해 버리는 내장 함수 @divTrunc를 같이 살펴볼게요. 이 글에서는 이 함수가 언제, 어떻게 쓰이는지를 해요체로 차근차근 설명드릴게요.

출처: Zig Documentation

본문

@divTrunc(numerator: T, denominator: T) T

@divTrunc는 **절사 나눗셈(truncated division)**을 수행해요. 결과를 0을 향해 반올림(정확히는 버림)한다는 뜻이에요.

계산 결과가 정확히 나누어떨어지지 않을 때, 음수든 양수든 0에 가까운 쪽으로 값을 잘라내요. 예를 들어 -5 / 3은 수학적으로 -1.666...인데, 이것을 0을 향해 버리면 -1이 되는 거죠.

부호 없는 정수(unsigned integer)에 대해서는 numerator / denominator와 완전히 동일해요. 음수가 없으니 그냥 일반 나눗셈과 같다고 생각하시면 돼요.

호출하는 쪽(코더)이 아래 조건을 보장해야 해요:

  • denominator != 0 (0으로 나누면 안 됩니다)
  • !(@typeInfo(T) == .int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1) — 즉, 부호 있는 정수에서 minInt(T) / -1 같이 오버플로우가 터지는 조합이면 안 됩니다.

이 계약을 지키면 함수는 오버플로우 검사를 생략하고 더 빠르게 동작해요.

다음은 이 함수의 핵심 성질을 보여주는 예시예요:

@divTrunc(-5, 3) == -1
(@divTrunc(a, b) * b) + @rem(a, b) == a

두 번째 식이 특히 중요해요. 몫과 나머지(@rem)를 합치면 항상 원래 값 a로 돌아온다는 정수 나눗셈의 기본 항등식을 보여주는 거예요. 이 관계 덕분에 몫과 나머지가 서로 짝을 이뤄 정확한 복원이 가능합니다.

만약 나눗셈이 실패했을 때 에러 코드(error code)를 돌려받고 싶다면, 표준 라이브러리 함수인 @import("std").math.divTrunc를 사용하는 게 좋아요.

관련 함수 (See also)

  • @divFloor — 음의 무한대(-∞)를 향해 버리는 나눗셈
  • @divCeil — 양의 무한대(+∞)를 향해 올리는 나눗셈
  • @divExact — 정확히 나누어떨어지는 경우에만 쓰는 나눗셈

더 알아보기 (Learn more)

  • @divFloor음의 방향으로 버림하는 동작이 @divTrunc와 어떻게 다른지 비교해보세요.
  • @divCeil@divExact가 각각 어떤 상황에서 필요한지 생각해보면, 정수 나눗셈의 네 가지 변형(@divTrunc, @divFloor, @divCeil, @divExact)을 한 번에 정리할 수 있어요.
  • @rem(나머지)와 함께 쓰는 항등식 (@divTrunc(a, b) * b) + @rem(a, b) == a를 직접 검증해보세요.