컴퓨터에서 소수는 부동 소수점(floating point) 방식으로 표현됩니다. C++에서 float 자료형은 일반적으로 32비트 크기를 가지며, 이러한 부동 소수점 숫자를 다루는 다양한 함수들이 <cmath> 헤더에 정의되어 있습니다. 이번 글에서는 대표적인 부동 소수점 조작 함수들의 용도와 사용법을 예제 코드와 함께 하나씩 살펴보겠습니다.
fmod() – 나눗셈의 나머지 구하기
fmod() 함수는 전달된 두 인자를 나누었을 때의 나머지를 반환합니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main() {
float a, b, rem;
a = 23.4;
b = 4.1;
rem = fmod(a, b);
cout<<"fmod("<<a<<", "<<b<<")의 값 = "<<rem;
}
출력 결과
fmod(23.4, 4.1)의 값 = 2.9
remainder() – 최소 나머지 구하기
remainder() 함수도 fmod와 마찬가지로 나눗셈의 나머지를 구하지만, 중요한 차이점이 있습니다. remainder()는 수학적으로 가능한 가장 작은 나머지를 반환하며, 그 결과는 음수가 될 수도 있습니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main() {
float a, b, rem;
a = 23.4;
b = 4.1;
rem = remainder(a, b);
cout<<"remainder("<<a<<", "<<b<<")의 값 = "<<rem;
}
출력 결과
remainder(23.4, 4.1)의 값 = -1.2
remquo() – 몫과 나머지를 동시에 구하기
remquo() 함수는 두 값의 나머지뿐만 아니라 몫까지 함께 구할 수 있는 함수입니다. 함수 호출 시 몫을 저장할 int 변수의 참조(포인터)를 세 번째 인자로 전달하면, 반환값으로는 remainder()와 동일한 방식의 최소 나머지를 돌려주고, 참조된 변수에는 몫이 저장됩니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main() {
float a, b, rem;
int quo;
a = 23.4;
b = 4.1;
rem = remquo(a, b, &quo);
cout<<a<<"과 "<<b<<"를 remquo() 함수에 전달한 결과\n";
cout<<"나머지: "<<rem<<endl;
cout<<"몫: "<<quo;
}
출력 결과
23.4과 4.1를 remquo() 함수에 전달한 결과 나머지: -1.2 몫: 6
copysign() – 부호 복사하기
copysign() 함수는 첫 번째 인자의 크기(magnitude)와 두 번째 인자의 부호를 결합한 값을 반환합니다. 즉, 반환값의 절댓값은 첫 번째 인자와 같고, 부호는 두 번째 인자를 따르게 됩니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b;
a = 9.6;
b = -3.5;
cout<<"입력값 "<<a<<"과 "<<b<<"에 대한 copysign 결과: "<<copysign(a, b);
}
출력 결과
입력값 9.6과 -3.5에 대한 copysign 결과: -9.6
fmin() – 최솟값 구하기
fmin() 함수는 이름 그대로 두 인자 중 더 작은 값을 반환합니다. 반환 타입은 부동 소수점이며, NaN처럼 특수한 값이 섞여 있어도 안정적으로 동작한다는 장점이 있습니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b;
a = 43.5;
b = 21.2;
cout << a<<"과 "<<b<<" 중 더 작은 값은 ";
cout << fmin(a, b)<<endl;
}
출력 결과
43.5과 21.2 중 더 작은 값은 21.2
fmax() – 최댓값 구하기
fmax() 함수는 두 인자 중 더 큰 값을 반환하는 함수입니다. fmin()과 마찬가지로 특수한 부동 소수점 값에 대해서도 안정적인 동작을 보장합니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b;
a = 43.5;
b = 21.2;
cout << a<<"과 "<<b<<" 중 더 큰 값은 ";
cout << fmax(a, b)<<endl;
}
출력 결과
43.5과 21.2 중 더 큰 값은 43.5
fdim() – 양의 차이 구하기
fdim() 함수는 두 인자 간의 양의 차이(positive difference)를 반환합니다. 첫 번째 인자가 두 번째 인자보다 크면 두 값의 차이를, 그렇지 않으면 0을 반환합니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b;
a = 43.5;
b = 21.2;
cout << a<<"과 "<<b<<"의 차이는 ";
cout << fdim(a, b)<<endl;
}
출력 결과
43.5과 21.2의 차이는 22.3
fma() – 융합 곱셈-덧셈 연산
fma() 함수는 Fused Multiply-Add의 약자로, 세 개의 인자 x, y, z에 대해 x × y + z 연산을 한 번의 명령으로 수행합니다. 중간 결과를 반올림하지 않고 계산하기 때문에 곱셈과 덧셈을 따로 수행하는 것보다 정확도가 높고 속도 면에서도 유리합니다.
예제
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double a, b, c;
a = 3.5;
b = 2.4;
c = 7.2;
cout << a<<" × "<<b<<" + "<<c<<"의 결과는 ";
cout << fma(a, b, c)<<endl;
}
출력 결과
3.5 × 2.4 + 7.2의 결과는 15.6
마무리
지금까지 <cmath> 라이브러리에서 제공하는 대표적인 부동 소수점 조작 함수들을 알아보았습니다. fmod와 remainder의 나머지 계산부터 remquo의 몫·나머지 동시 처리, copysign의 부호 조작, 그리고 fmin, fmax, fdim, fma까지, 이 함수들을 적절히 활용하면 실수 연산을 더욱 정확하고 편리하게 처리할 수 있습니다.