[펌] float -> int 형변환 정리
방법1) FPU를 이용한 인라인 어셈코드입니다.
int fastf2i_round(float f)
{
#ifdef _WIN32
int i;
__asm
{
fld f
fistp i
}
return i;
#else
return (int)(f + 0.5f);
#endif
}
장점 : 가장 빠릅니다.
단점 : 반올림이 됩니다. 따라서 int a = int(1234.56f) 와 같은 값이 안 나온다는 것입니다. 반올림되어서 1235가 나옵니다.
방법2) 역시 FPU를 이용한 인라인 어셈코드이지만 반올림을 안하도록 약간의 조정을 합니다.
int fastf2i(float fValue)
{
#ifdef _WIN32
static const float round_to_nearest = -0.499999f;
int iValue;
__asm
{
fld fValue
fadd round_to_nearest
fistp iValue
}
return iValue;
#else
return (int)fValue;
#endif
}
장점 : 역시 방법1과 흡사하게 빠릅니다.
단점 : 방법1에서 반올림이 안되도록 반올림값을 빼주고 있습니다만 0.9999999f식의 값이 들어오면 역시 반올림됩니다. 물론 round_to_nearest 를 약간 상황에 맞게 수정하면 되는 것입니다만 약간 찝찝한 것 사실입니다.
방법3) int변환을 그대로 인라인 어셈화 하였습니다.
int Float2Int( float a )
{
#ifdef _WIN32
int CtrlwdHolder;
int CtrlwdSetter;
int RetVal;
__asm
{
fld a // push 'a' onto the FP stack
fnstcw CtrlwdHolder // store FPU control word
movzx eax, CtrlwdHolder // move and zero extend word into eax
and eax, 0xFFFFF3FF // set all bits except rounding bits to 1
or eax, 0x00000C00 // set rounding mode bits to round down
mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid!
fldcw CtrlwdSetter // Entering plaid!
fistp RetVal // Store and converted (to int) result
fldcw CtrlwdHolder // Restore control word
}
return RetVal;
#else
return (int)a;
#endif
}
장점 : 일반 int형변환과 정확히 일치합니다.
단점 : 그다지 많이 빠르지 않네요.
방법4) Game Programming Gems2 chapter 2.1에 Yossarian King씨가 작성한 방법입니다.
typedef union
{
int i; // as integer
float f; // as float
struct // as bit fields
{
unsigned int sign:1;
unsigned int biasedexponent:8;
unsigned int significand;
} bits;
} INTORFLOAT;
INTORFLOAT FTOIBIAS = {((23 - 0 + 127) << 23) + (1 << 22)};
int f2i(float f)
{
INTORFLOAT ftmp;
ftmp.f = f;
ftmp.f += FTOIBIAS.f;
ftmp.i -= FTOIBIAS.i;
return ftmp.i;
}
장점 : FPU모드에 따라 일반적으로 일반 int형변환과 정확히 일치합니다.
단점 : float의 값이 2의 23승(8388608)보다 작아야 합니다. 또한, FPU모드가 Chopping이 아닌 경우. 예를 들면 위의 fastf2i_round나 fastf2i와 같이 사용하면 안됩니다. fastf2i_round나 fastf2i는 FPU모드를 반올림모드로 사용하는데, f2i함수는 FPU모드를 따로 설정하지 않기 때문에 현재 FPU모드 그대로 변환을 시도합니다. (FPU모드는 위의 참고를 보시기 바랍니다)
결론) 복잡하시죠? ^^
반올림이 상관없을 때는 fastf2i_round를 사용하세요.
일반 int형변환과 같이 같은 값이 나오기를 바라신다면 fastf2i나 Float2Int를 사용하세요.
출처 : http://cafe.naver.com/jzsdn/11238
'Tip & Tech' 카테고리의 다른 글
[펌] 윈도우 안전한 프로그래밍[Runtime Check] (0) | 2011.06.11 |
---|---|
[펌] fatal error C1083: 미리 컴파일된 헤더 파일을 열 수 없습니다. (0) | 2011.06.11 |
[펌] 기업에서까지 완전 무료 프로그램 - 진정한 FREE!! (0) | 2011.06.08 |
[펌] 매크로 마법 (Macro) (2) | 2011.06.08 |
[펌] !!a (0) | 2011.06.08 |