lang/php

php integer 크기

C/H 2010. 9. 28. 08:30
PHP INTEGER 크기

$large_number = 2147483647;
var_dump($large_number);
// output: int(2147483647)

$large_number = 2147483648;
var_dump($large_number);
// output: float(2147483648)

PHP 에서 제공하는 정수는 10자리 2147483647 까지 입니다.

Facebook 에서 제공하는 API로 이전 Feed를 업데이를 할 때는 결과값이
/me/feed 로 요청을 보내서 Array('id' => '{fb_id}_{feed_id}', ... ) 형식으로 결과가 넘어 오는 관계로 이대로 값을 활용했는데

개발중인 서비스가 url을 다루는 관계로 links 로 변경을 했더니 결과값이 다르게 넘어와서 문제가 생겼습니다.
/me/links 로 요청을 보낸 결과 Array('id' => '{links_id}') 2010.09.27 현재 결과 id 는 15자리 정수입니다.

위 에서 결과로 넘어오는 id 값중 feed_id 와 links_id 는 브라우즈에서 접근이 가능한 "story_fbid={id}" 입니다.

문제는 PHP에서 10자리를 초과하는 값을 float로 자동변환해 버린다는 문제입니다. 결과값을 그대로 DB에 저장을 해 버리면 값이 제대로(?) 저장이 되는거 같은데 가끔 그것도 아닌거 같더군요.

현재 facebook API lib 는 facebook에서 제공하는 lib를 사용하는 관계로 결과값을 json으로 받아서 json_decode를 사용해서 연관배열로 변환한 값입니다.

PHP 5.3 버전 이상에서는 json_decode에서 BIGINT 이상일 경우 STRING형태로 반환하는 기능이 있으나 서비스중인 PHP 버전이 그 이하 버전이므로 패스~

class lib로 제공되는 Services_json 을 확인해보니 BIGINT에 대한 기능은 없었습니다.

facebook 결과값을 (string)$fb['id'], srtval($fb['id']) 형태로 변환할 경우 앞에서 12자리까지만 제대로 반환되고 나머지 3자리는 0을 반환해서 사용불가.

그외 php 변수 크기의 한계를 넘는 듯 합니다. 에서 정보를 얻어
위 2가지 lib를 확인했지만 이미 결과로 넘어온 값을 PHP에서 제대로 뽑아 낼수 없었습니다.

그래서 임시로 number_format기능을 사용해서 원하는 값을 얻어 냈습니다.
/*
$fb = $this->db->api(
 '/me/feed',
 'post',
 Array(
  'message' => 'message'
 )
);
if(isset($fb['db'])) $id = $fb['id'];
*/

$fb = $this->fb->api(
 '/me/links',
 'post',
 Array(
  'message' => 'message',
  'link' => 'url'
 )
);
/**
* TODO : 
* /me/link 결과 $fb['id'] 값은 {links_id} 15자리 숫자 형식.
* PHP에서 제공하는 정수 숫자 자리수는 10자리. 
* 현재 임시로 제공한 number_format는 17자리(12345678901234567)까지는 정확한 값을 리턴.
* number_format(999999999999999999) => 9,999,999,999,999,999,xxx,xxxx
* 5.3 이상에서 json_decode 에서 BIGINT를 STRING으로 반환하는 기능이 추가되었으나 현재 현재서비스중인 PHP는 5.3 미만 버전.
*/
if(isset($fb['db'])) $id = mem('fb_id').'_'.str_replace(',', '', number_format($fb['id']) );


얼마동안은 문제가 없겠지만 결국은 json_decode 시 BIGINT이상의 값을 STRING으로 변환해서 반환하는 기능으로 변경되어야 할것 같습니다.

number_format 에서 어느정도의 숫자를 커버하는지 궁금하군요. 특정숫자에서는 15자리까지 확인했지만 이것도 문제네요

2010.11.18

웃기게도 ip2long 에서 해결방법이 있는거 같네요.

PHP ip2loing

$dottedFormatAddress = '127.0.0.1'; 
$ipv4address = sprintf("%u", ip2long($dottedFormatAddress));

위 예제에서 사용한 sprintf("%u", $int); 형식으로 반환이 가능할거 같긴 하네요.
일단은 테스트를 해봐야 겠습니다.


반응형