고정소수점 구현해보기 1. 사칙연산

Posted by 적분 ∫2tdt=t²+c
2012.10.11 17:46 프로그래밍/테크닉

고정소수점은 우리가 흔히 사용하는 float나 double과는 달리 소수점 자리가 늘 고정한 채로 실수를 표현하는 방식을 말합니다. 표현범위가 넓지 않아서 자주 쓰이지는 않지만, 정밀도가 그다지 필요없는 경우, 단순한 실수연산을 위해서 사용할수가 있습니다.


대표적인 예로 스타크래프트2 트리거나 게임 데이터에서 사용되는 실수가 고정소수점이라고 판단되는데요, 예를 들어 유닛의 체력과 같은 경우, 그냥 정수형 데이터가 사용될거 같지만, 실제로는 고정소수점 포맷을 사용하는거 같습니다.(제가 개발자가 아니라 정확히는 모르지만... 여러가지 정황을 보고 추측하는 것입니다.) 저그 유닛은 초당 체력이 0.24씩 회복이 되어야하니 정수형 데이터를 쓰기에는 좀 뭐시기하지요. 부동소수점형을 쓰기엔 연산 부하가 많이 걸릴거같고... 이럴때 고정소수점 데이터가 적격입니다.


자 고정소수점 데이터 타입 Fixedp을 정의해봅시다. 32비트 정수에서 상위 24비트는 정수부분을 표현하는데 쓰고, 하위 8비트를 소수부분을 표현하는데 이용해봅시다.

즉 임의의 32비트 정수 n이 을 나타내도록 정의하자는 것입니다.

그러면 어떤 수 x를 Fixedp로 표현하기 위해선 256을 곱하면 됩니다. x가 정수라면 간단하게 x << 8이 되는거지요.


덧셈/뺄셈 구현은 간단합니다.

이므로 두 고정소수점을 더하기 위해선 그냥 두 수를 더하면 됩니다.

뺄셈도 마찬가지.


문제는 곱셈과 나눗셈이 약간 까다로운데


이므로 곱셈은 그냥 두 a b를 곱하는 것이 아니라, 곱한뒤에 256으로 나눠줘야합니다.



이므로 나눗셈은 a/b를 하는것이 아니라 256a 에서 b를 나눠야합니다.


자, 이 사실을 바탕으로 다음과 같은 코드를 작성할수 있습니다.



단순한 코드입니다. 덧셈뺄셈은 따로 함수조차 만들지 않았습니다.ㅋ

곱셈과 나눗셈에서 long long으로 캐스팅해서 오버플로우로 인한 데이터 손실을 막았다는거 빼고는 밋밋한 코드네요.


그 밑에 FIXEDP를 문자열로 변환해주는 함수도 짜보았습니다. 소수점이 8비트 할당되었으므로

이기에, 소수점이하 2자리정도까지가 유효자리고 나머지는 오차가....ㄷㄷ

그래서 소수점이하 세 자리까지만 출력하도록 했습죠.



역시나 성능이 문제인데, 집 컴에서 돌려보니 덧셈, 뺄셈, 곱셈은 부동소수점 연산과 비슷하거나 미묘하게 빨랐고, 나눗셈연산은 절망적으로 느렸습니다.ㅠㅠ 역시 정수 나눗셈은 정말로 느리구나.... 어쩌면 그냥 부동소수점 연산 쓰는게 나을지도 모르겠네요ㅋ

이 댓글을 비밀 댓글로