이번 글에서는 C/C++에서 제공하는 nextafter()와 nexttoward() 함수가 어떤 역할을 하는지 자세히 살펴보겠습니다. 두 함수 모두 <math.h>(C) 또는 <cmath>(C++) 헤더 파일에 정의되어 있습니다.
nextafter()와 nexttoward()란?
nextafter(a, b) 형태로 호출하면, 첫 번째 인자 a를 기준으로 두 번째 인자 b 방향에 위치한 표현 가능(representable)한 바로 다음 부동소수점 값을 반환합니다. 예를 들어 nextafter(0.0, 1.0)은 0보다 크면서 1쪽 방향에 있는, double 타입으로 나타낼 수 있는 가장 작은 양수를 돌려줍니다.
두 함수의 핵심적인 차이점은 두 번째 매개변수의 정밀도에 있습니다. nexttoward()는 두 번째 인자를 long double 타입으로 받기 때문에 nextafter()보다 더 정밀한 방향 지정이 가능합니다. 만약 a와 b가 동일한 값이라면 b가 그대로 반환됩니다.
예제 코드
#include <stdio.h>
#include <math.h>
int main() {
// nextafter() 함수 사용
printf("0에서 1 방향으로 표현 가능한 가장 작은 수 : %e\n", nextafter(0.0, 1.0));
printf("0에서 -1 방향으로 표현 가능한 가장 큰 수 : %e\n", nextafter(0.0, -1.0));
printf("0.8 근처(0 방향)의 표현 가능한 값 : %e\n", nextafter(0.8, 0.0));
// nexttoward() 함수 사용
printf("\n");
printf("0에서 1 방향으로 표현 가능한 가장 작은 수 : %e\n", nexttoward(0.0, 1.0));
printf("0에서 -1 방향으로 표현 가능한 가장 큰 수 : %e\n", nexttoward(0.0, -1.0));
printf("0.8 근처(0 방향)의 표현 가능한 값 : %e\n", nexttoward(0.8, 0.0));
return 0;
}
실행 결과
0에서 1 방향으로 표현 가능한 가장 작은 수 : 4.940656e-324 0에서 -1 방향으로 표현 가능한 가장 큰 수 : -4.940656e-324 0.8 근처(0 방향)의 표현 가능한 값 : 8.000000e-001 0에서 1 방향으로 표현 가능한 가장 작은 수 : 4.940656e-324 0에서 -1 방향으로 표현 가능한 가장 큰 수 : -4.940656e-324 0.8 근처(0 방향)의 표현 가능한 값 : 8.000000e-001
결과 분석
첫 번째 출력값인 4.940656e-324는 double 타입으로 표현할 수 있는 최소 양수, 즉 비정규화(denormalized) 부동소수점 수입니다. 음수 방향 역시 절댓값이 같은 최솟값이 존재합니다.
nextafter(0.8, 0.0)의 결과가 8.000000e-001로 표시되는 이유는 %e 서식 지정자가 기본적으로 6자리 유효숫자만 출력하기 때문입니다. 실제 반환값은 0.8과 인접하지만 미세하게 다른 값이며, %.17e처럼 유효숫자를 늘려 출력하면 그 차이를 확인할 수 있습니다.
두 함수는 부동소수점 오차 분석, 수치 알고리즘 검증, ULP(Unit in the Last Place) 계산 등 정밀한 수치 처리가 필요한 상황에서 매우 유용하게 활용됩니다.