2013-10-22 8 views
0

나는 (테이블의 키가있는) BIGINT 값의 PHP 표현을 실험하고있어, 나는 작은 시험을 썼다 PHP 문자열/부동 소수점 값으로 많은 수를 처리하는 방법을 테스트 :PHP BIGINT 표현

<?php 
echo "PHP_INT_MAX=".PHP_INT_MAX."\n"; 
$x = "9223372036854775107"; 
echo "Defining x as : 9223372036854775107\n"; 
$y = floatval($x); 
echo "float of x: ".$y."\n"; 
echo "float to string using strval: ".strval($y)."\n"; 
echo "float to string using sprintf: ".sprintf("%.0f", $y)."\n"; 
?> 

을 그래서 출력에 대해 궁금합니다.

PHP_INT_MAX=9223372036854775807 
Defining x as : 9223372036854775107 
float of x: 9.2233720368548E+18 
float to string using strval: 9.2233720368548E+18 
float to string using sprintf: 9223372036854774784 

그런데 왜 일치하지 않는 값이 표시됩니까? (php.ini 파일의 정밀도 = 12)

+0

그들이 나에게 일치처럼 그들은 찾습니다 차이는 어디? –

+0

당신은 정밀도 설정을 알고 있습니다 -이 숫자에서'92233720368548'은 14 자리 유효 숫자입니다. 설정을 20으로 늘리면 원하는대로 볼 수 있습니다. –

+0

동일한 테스트를 ini_set ('precision', 32)과 함께 추가했습니다. 여전히 같은 (마크! : 9223372036854775107는 = 9223372036854774784) 얻을 –

답변

1

플로트 타입이 전부입니다. PHP는 일반적인 서체 인 IEEE 754을 사용합니다.

플로트 크기는 64입니다. 64 시스템 정수 크기도 64입니다. 정밀도의 손실없이 소수 부분이없는

그러나 최대 부동 소수점 수는보다 9007199254740991. 숫자 이상으로 인해 형식으로 저장하는 부동 소수점 숫자, 자신의 정밀도를 잃을 것입니다. 2^52 = 4,503599627370,496 2^53 = 9,007199254740,992 표현할 수있는 숫자 사이

정확히 정수이다. 다음 범위 인 2^53에서 2^54까지는 모든 것이 2로 곱해 지므로 표현 가능한 숫자는 짝수입니다. 반대로 이전 범위가 2^51에서 2^52 인 경우 간격은 0.5입니다. 등

N^2^N + 1 (2)의 범위에있는 번호의 일부 등 간격이 2^N-52이다. 따라서 가장 가까운 대표 값 (기계 엡실론)으로 숫자를 반올림 할 때 최대 상대 반올림 오류는 2^-53입니다.

Double-precision floating-point format

+0

흥미 롭습니다! 그래서 기본적으로 이것은 우리가 BIGINT 값을 표현하기 위해 float을 사용해야한다는 것을 의미하며, 9007199254740991 (이는 손실없이 성공적으로 표현됩니다)을 초과해서는 안됩니다 ... 나는 우리가 마음과 sectus를 유지할 것이라고 생각합니다. –

+0

또한 산술 연산에서 부동 소수점의 정밀도를 잃을 수 있습니다. – sectus