삽질하는플머

PHP 에서 Int64 숫자값 문제

탐구생활/WEB 관련
PHP의 최대 정수값은 다음 코드로 살펴볼 수 있다. 

echo PHP_INT_MAX;



이 값은 32비트에서는 2,147,483,647. 64비트에서는 9,223,372,036,854,775,807 이다. 하지만 윈도에서는 32비트건 64비트건 관계없이 2,147,483,647 이다. (참고링크 : http://www.pubbs.net/200902/php/3781-re-php-dev-casting-doubles-to-ints.html)
 
내 경우 게임 캐릭터의 사이버머니 또는 현금의 필드값은 BIGINT, 즉 Int64 형을 쓰고 있다. 비교에서 사용될 경우야 단순히 문자열로 간주하면 상관없지만, 이렇게 '돈'에 관련된 경우는 상황이 조금 다르다. 직접적으로 값을 박아넣는 것이 아니라 기존값에 대해 증가시키거나 차감시키는 방식으로 처리하는 '연산'이 필요하기 때문이다. 따라서 PHP의 정수값 한계는 문제가 된다. 

게다가 PHP는 큰 정수의 경우 자동으로 실수값으로 변환해 처리하게 된다. 정수 한계를 벗어나는 큰 수를 변수에 넣고 출력해보자.

$k = 703687441776631235523;

echo $k;
echo sprintf('%f', $k);



출력결과는

7.0368744177663E+20
703687441776631218176.000000



이처럼 입력값과 전혀 관계없는 부정확한 값이 찍히게 된다.

일단 떠오르는 해법은 두가지. 스토어드 프로시저를 써서 MySQL에서 현금값을 차감하는 함수를 만들고 이것을 호출하는 방법. 
두번째는 BCMath(http://kr2.php.net/bc), 또는 GMP(http://www.php.net/manual/en/book.gmp.php) 를 사용하는 방법.

GMP는 잘 모르겠고, BCMath의 경우는 우분투, 윈도용 WAMP, NAS 세군데 모두 번들되어있다. 따라서 이 녀석을 쓰자.

$m = bcadd("703687441776631235523", "1", 0);
echo $m . '<BR>';


 
출력결과는 다음과 같다.

703687441776631235524


 
bcadd 의 마지막 인자는 결과값에서 사용할 소수점 자릿수. 정수만 쓰려면 0을 준다. 
또는 bcscale() 함수로 전역적으로 설정할 수도 있다.

bcscale(0);
$m = bcadd("703687441776631235523", "1");
echo $m . '<BR>';


 
BCMath 에는 이 외에도 빼기, 나누기, 곱하기, 승수 처리함수가 내장되어있다. 두 숫자가 같은지 비교하는 bccomp 도 유용하다. 
이로서 DB에 들어있는 BIGINT 현금값을 문자열로 간주, BCMath로 비교후 차감한 뒤 그 결과값을 돌려줄 수 있게 되었다.