Abseil Tip 231 여기와 저기 사이 – 간과되기 쉬운 몇 가지 알고리즘

아래는 “이번 주의 팁 #231: 여기와 저기 사이 – 간과되기 쉬운 몇 가지 알고리즘”에 대한 한글 번역입니다.


제목: “이번 주의 팁 #231: 여기와 저기 사이 – 간과되기 쉬운 몇 가지 알고리즘”

원문 게시일: 2024년 3월 7일
업데이트: 2024년 9월 30일

작성자: James Dennett

빠른 링크: abseil.io/tips/231


개요

최근 C++ 표준 라이브러리에는 두 점 xy 사이의 특정 지점을 계산하는 몇 가지 함수가 추가되었습니다:

  • std::clamp (C++17 도입)
  • std::midpoint, std::lerp (C++20 도입)

이 함수들의 주요 목적은 다음과 같습니다:

  1. 공통 용어를 제공하여 코드의 의도를 명확히 표현합니다.
  2. 특히 std::midpointstd::lerp의 경우, 일반적인 함정을 피하면서 고품질 구현을 제공합니다.

모든 함수는 constexpr로 정의되어 있어 컴파일 타임런타임 모두에서 사용할 수 있습니다.
함수마다 지원하는 타입은 다르지만, 모든 함수가 부동소수점 타입(floating point)을 지원하며, 일부는 정수 타입이나 포인터 타입에도 유연하게 적용됩니다.


1. std::clamp

std::clamp(x, min, max)x[min, max] 범위로 “클램프(clamp)”합니다.
즉, x가 해당 범위 내에 있으면 그대로 반환하고, 범위를 벗어나면 가장 가까운 경계 값인 min 또는 max를 반환합니다.

auto clamped = std::clamp(10, 5, 7); // clamped == 7
auto within_range = std::clamp(6, 5, 7); // within_range == 6

이 함수는 std::max(std::min(x, max), min)과 동일한 동작을 하지만, 더 직관적으로 의도를 표현합니다.

주의:
std::clamp참조(reference)를 반환합니다.
이를 의존해 코드를 작성하면 섬세한 오류를 유발할 수 있으므로 피해야 합니다.

const int& dangling = std::clamp(1, 3, 4); // 잘못된 코드: dangling 참조가 소멸된 값을 가리킬 수 있음.

2. std::midpoint

std::midpoint(x, y)xy 사이의 중간 지점을 반환합니다.

  • 정수 타입의 경우, x 쪽으로 반올림하여 결과를 계산합니다.
  • 부동소수점 타입에서는 정확한 중간값을 계산합니다.

추가적으로, std::midpoint(p, q)는 배열 내의 두 포인터 pq의 중간 지점을 반환할 수도 있습니다.

auto mid = std::midpoint(10, 20); // mid == 15
auto float_mid = std::midpoint(10.5, 20.5); // float_mid == 15.5

3. std::lerp

std::lerp(x, y, t)xy 사이에서 비율 t만큼 떨어진 값을 반환합니다.

  • t = 0이면 x를 반환합니다.
  • t = 1이면 y를 반환합니다.
  • t = 0.5xy의 중간 지점을 반환합니다. (이 경우 std::midpoint와 동일)
auto lerp_result = std::lerp(10, 20, 0.25); // lerp_result == 12.5

외삽(extrapolation)도 가능합니다:

  • t[0, 1] 범위를 벗어나도 동작하며, 결과는 선형적으로 계산됩니다.
auto extrapolate_low = std::lerp(100, 101, -2); // extrapolate_low == 98
auto extrapolate_high = std::lerp(100, 101, 2); // extrapolate_high == 102

권장 사항

  1. 표준 라이브러리를 활용하세요.
    이러한 함수들은 일반적인 작업을 더 명확하고 간결하게 표현할 수 있도록 설계되었습니다.

  2. std::midpoint(x, y)를 사용할 수 있는 경우 std::lerp(x, y, 0.5) 대신 사용하세요.
    • std::midpoint는 명확성과 성능 면에서 더 나은 선택입니다.
  3. std::clamp의 반환값에 대한 참조를 사용하지 마세요.
    참조를 사용한 코드는 미묘한 오류를 유발할 가능성이 크므로, 단순히 값을 사용하는 것이 더 안전합니다.

이 함수들은 C++ 코드에서 흔히 필요한 작업들을 더 안전하고 명확하게 처리할 수 있도록 도와줍니다.
이를 활용하여 더 나은 품질의 코드를 작성해 보세요!