#cpp float를 int로 conversion할 때 일어나는 일

1 minute read

The conversion truncates; that is, the fractional part is discarded.

4.9 Floating-integral conversions, ISO/IEC 14882

표준에 정의된 float에서 integer의 변환은 fractional part를 버리는 것으로 이루어 진다. *내림이 아니라 버리는 것*이다.

std::cout << "static_cast<int>(4.6f) = " << static_cast<int>(4.6f) << std::endl;
std::cout << "static_cast<int>(-5.3f) = " << static_cast<int>(-5.3f) << std::endl;
static_cast<int>(4.6f) = 4
static_cast<int>(-5.3f) = -5

여기까지는 기본적인 내용이다. 내부적으로 한 번 살펴보면, MS Visual Studio에서는 _ftol() 함수를 호출해서 변환을 한다. _control87, _controlfp, __control87_2를 사용해 rounding 방법을 바꿀 수도 있다.

the _ftol function ensures the rounding mode of thefloating-point unit (FPU) is toward zero (truncate), by setting bits 10and 11 of the control word. This guarantees that converting from afloating-point type to an integral type occurs as described by the ANSIC standard (the fractional portion of the number is discarded).

Visual C++ Compiler Options /QIfist (Suppress _ftol)

하지만 /QIfist 옵션을 사용하면 _ftol() 함수를 호출하지 않고 FPU(Floating-Point Unit)의 기본 rounding 모델인 반올림을 수행하게 된다.

1>cl : Command line warning D9035 : option 'QIfist' has been deprecated and will be removed in a future release

한번 테스트 해 보려고 간단히 만들어서 컴파일 하니 warning이 발생한다. VS 2005에서 deprecated 되었다고 한다.

이전에 이것때문에 완전 삽질을 한 기억이 난다. Debug 버전에서는 잘 돌아가는데, 이상하게 Release 버전에서만 오동작을 하는 것이다. 이리저리 버그를 찾다보니 소스 코드에 float에서 int로 conversion 하는 곳이 있는데, 여기서 반올림 되는 것이다. 프로젝트 옵션을 보니 /QIfist 가 있더라. 역시 디버깅 할때는 다 의심해 봐야한다.

이제 뭐~ 2005 부터는 이런 일도 안 벌어지겠지~