scaleform.minarto.com

부동소수점 이야기...클라이언트와의 통신 본문

Communication

부동소수점 이야기...클라이언트와의 통신

미나토 2012. 1. 13. 17:46


새해 첫 포스팅입니다... 뭔가 야심차게 한번!!!



서로 문제 없이 프로그래밍을 했는데 문제가 있다???
 


클라이언트와 통신으로 숫자를 주고 받던 도중 이상한 값들이 들어와서 한동안 헤맸던 적이 있습니다...

아무리 확인해도 애초에 잘못된 값이 들어오는데, 클라이언트는 아무리 확인해도 제대로 된 값을 던져줬다는 것이지요...

이것이 다 서로의 언어에 대한 몰이해에서 시작된 것입니다...


Number, int, uint 플래시에서는 이렇게 세가지의 숫자 타입을 가지고 있습니다

uint 는 32bit 형의 정수형이고, int 는 32bit의 부호가 있는 (음수, 양수) 정수형입니다...
그러다 보니, int는 부호에 1bit를 나눠주느라 31bit (2^31 - xor 연산자 말고 승수요) 만을 사용합니다...

as2에서는 Number 형만 가지고 있습니다...


자 이제 Number 에 대해서 알아보겠습니다... 레퍼런스를 보니 53bit 를 사용하고 있다고 합니다.(http://help.adobe.com/ko_KR/FlashPlatform/reference/actionscript/3/Number.html)

하지만 이중에서 하나는 부호입니다... 그러니 실제로는 52bit 만을 숫자에 활용합니다... 그런데 뭔가 이상하지 않나요? 프로그래밍인데 2의 승수인 32bit도 아니고, 64bit도 아닌 52bit 라니 말이죠...

이건 뭔가 이상합니다...

결론부터 말씀드리자면 사실 플래시의 Number는 64bit를 사용하고 있습니다...





실수를 메모리에 어떻게 표현할 것인가...


실수를 64bit라는 메모리에 표현하려면 어떻게 해야할까요... 간단하게 생각하면 1bit 부호 + 32bit 는 정수 + 31bit는 소수로 하면 될 듯 합니다...

그런데 그러고 보니 실수의 표현 범위가 너무나 작은겁니다... 그럼 1024bit쯤 할애하면 되잖아!!! 라고 말할 수도 있겠지만... 프로그래밍의 세계가 우리가 원하는 대로 해줄만큼 만만치가 않습니다.

그래서 생각하게 된 것이 실수를 정수처럼 일단 표현하고 그 뒤에 소수점을 찍자는 겁니다...

123456789 쓰고선 첫번째에 찍으면 .123456789 가 되고, 다른데 찍으면 123456.789 도 되는 것이죠...

뭔가 아이디어는 좋은 거 같은데 중요한 것이 하나 빠졌습니다... 소숫점을 몇번째에 찍을 것인가에 대한 데이터는 그럼 어디에 저장해야 하나요???

그래서 컴퓨터에서 사용하게 된 것이 이진법을 밑수로 한 부동소수점 표기법입니다...
(전 솔직히 이 용어를 누가 지었는지 모르겠지만 불만이 많습니다... 일반적으로 한국 사람이 "부동" 이란 자를 생각하면 "不動" 을 생각하지 않나요???)



실수의 부동소수점 표기방법 

이진법을 밑수로 한 부동소수점 표기법...... 뭔가 되게 이름이 길지만 결국 다음과 같습니다...

0.4 = 0.8 * 2^(-1) 이 됩니다...
0.4 = 1.6 * 2^(-2) 도 물론 성립합니다...

이처럼 첫번째 숫자를 2(밑수) 밑의 수로 만들어 표현한 것을 정규화라고 합니다... 이걸 왜 하냐면... 무조건 1로 만들어준다는건 생략할 수도 있다는 말이고 그만큼 한자리를 더 표현할 수 있기 때문입니다...

1bit는 부호에 사용한다고 했습니다
52bit가 Number 의 범위라고 했지요... 자, 나머지 11bit는 바로 여기에 있습니다... 2의 - 승수입니다...

이에 따라 2진연산 오차도 생기는 것인데...  당연하게 52bit 이상을 실수에 쓰면 오차가 생기는 것이지요. 말했잖아요.... 52bit까지밖에 못쓴다니까요???
as3로 trace(1.3 - 1) 를 찍어보세요... 0.3을 기대하셨다면 안타깝다는 말씀밖에는 드릴 말이 없습니다...
제가 찍어보니 0.30000000000000004 가 나오는군요...


뭐 더 자세한건 위키백과를 찾아서 봐주세요... 이 포스팅이 이걸 얘기하려고 하는 것은 아니니까요...
부동소수점에 대한 글을 쓰려는게 아니라 통신에 대해 쓰려는 겁니다...




각 언어에서 지원하는 숫자타입


암튼 플래시에서는 저렇게 숫자를 사용합니다만... 다른 언어는 어떤가요...

전 플래시 말고는 배워본 적도 없는 비전공자이지만 여러 숫자타입이 있다는 것은 어깨너머 들어서 알고 있습니다... 그리고 같은 실수 표현법에도 플래시의 부동소수점 표기법에 따라 결과가 달라질 수 있습니다...



클라이언트에게 제가 인자를 던져달라고 할 때, 이렇게 말했습니다...

"숫자로 던져주세요..."

이제 게임회사 개발자로서는 이건 틀린 커뮤니케이션 방법이 된겁니다...
클라이언트가 52bit 이상의 숫자를 던져준다면??? 이정도까지 숫자를 쓸 일이 없다고요???

리니지 서비스한 지가 십수년이 흘렀죠??? 지금까지 모은 아덴이 있다면 얼마일 것 같나요???

만약 제가 누군가에게 우편으로 돈을 보냈는데, 플래시의 이진연산 오차로 잘못된 값을 보냈다면???
패치할때까지 게임서버 내리고... 버그를 찾아 찾아... 누구에게 책임이 돌아올까요???


단위가 매우 늘어날 수 있는 숫자타입은 차라리 String으로 던져주는 것이 안전합니다... 라고 결론을 내고 끝내고 싶은데...




그럼 뭘로 주고 받아야 하나요???


클라가 꼭 플래시처럼 문자열을 쓰란 법이 없습니다... 플래시는 문자가 아닙니다. 문자열입니다...
문자는 16bit 이고, 그에 따른 배열이란 말입니다.

바로 Vector.<int16> 이런걸 상상해보시면 딱 맞습니다...

여기에 관해서는 제가 참여한 e-book 을 보시면( http://itunes.apple.com/us/app/id456620773?l=ko&ls=1&mt=8 ) 홍보 한번!!!

c언어에서는 플래시처럼 vm이 알아서 메모리를 마구마구 늘려주는게 아니고 개발자가 다 잡아놓고 써야합니다...
플래시로 말하자면 위에 쓴 가상의 Vector.<int16> 가 fixed = true 가 된 것이죠...

만약  Vector.<int16> (4, true) 의 형태로 문자열을 잡아서 통신을 했다면 들어올 숫자는 딱 네자리인 셈입니다... 숫자로 주고 받는 것보다 더욱 최악의 상황이 벌어져버린 거죠...




그래서 어쩌라고??


길어지니 결론을 말하라고요???

상황에 맞게 얼마나 주고 받을지에 대해 미리 정의가 있어야 합니다..... 가 결론입니다... :^)
이게 사실 서버와의 통신이라면 데이터를 줄이기 위해 당연한 일인데, 클라이언트와의 통신은 그걸 잊어버립니다.


저같이 전산 비전공이고 플래시만 공부한 사람은 이런 이론적인 것에 대해 많이 모르기 때문에 이런 문제가 닥쳐도 그냥 미지의 버그로 남게되는 경우가 있습니다.
실제로 제가 처음 이진연산 오차를 접하고선 버그리포트로 올린 적이 있답니다...ㅡ.,ㅡ;;;

하지만, 게임 회사는 에이전시처럼 플래시만으로 뭔가가 돌아가는 회사가 아닙니다... 타 언어와의 통신은 필수입니다...

그렇다면, 타언어로 프로그래밍까지는 못하더라도... 어느정도의 이해는 필요한 것이죠...




참고 :

http://help.adobe.com/ko_KR/FlashPlatform/reference/actionscript/2/help.html?content=Part2_AS2_LangRef_1.html 

http://help.adobe.com/ko_KR/as3/learn/WSf00ab63af761f1702761490412937d6fc9b-7ff5.html 

http://help.adobe.com/ko_KR/FlashPlatform/reference/actionscript/3/Number.html 
 
http://ko.wikipedia.org/wiki/%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EC%A0%90  

http://wooyaggo.tistory.com/category/ActionScript%203.0