정수
정수 (Integer)
int는 집합 ℤ = {..., -2, -1, 0, 1, 2, ...} 에 속하는 숫자예요. PHP에서 정수는 소수점 없는 수를 말하며, 연산이나 비교의 기본 단위로 아주 자주 만나게 돼요.
문법 (Syntax)
정수는 십진수(밑수 10), 16진수(밑수 16), 8진수(밑수 8), 2진수(밑수 2) 표기로 쓸 수 있어요. 음수를 나타내려면 부정 연산자(negation operator) -를 붙이면 돼요.
진법 표기를 정리하면 이렇게 돼요.
- 8진수는 숫자 앞에
0(영)을 붙여요. PHP 8.1.0부터는0o나0O로도 쓸 수 있어요. - 16진수는 숫자 앞에
0x를 붙여요. - 2진수는 숫자 앞에
0b를 붙여요.
PHP 7.4.0부터는 가독성을 위해 숫자 사이에 밑줄(_)을 넣을 수 있어요. 이 밑줄은 PHP의 스캐너가 제거해 버리니 실행 결과에는 영향을 주지 않아요.
예제 #1 정수 리터럴
<?php
$a = 1234; // decimal number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0o123; // octal number (as of PHP 8.1.0)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
$a = 0b11111111; // binary number (equivalent to 255 decimal)
$a = 1_234_567; // decimal number (as of PHP 7.4.0)
?>
정수 리터럴의 형식을 공식적으로 나타내면 PHP 8.1.0 기준으로 아래와 같아요. (0o/0O 접두어와 밑줄은 그 이전 버전에서는 허용되지 않았어요.)
decimal : [1-9][0-9]*(_[0-9]+)*
| 0
hexadecimal : 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*
octal : 0[oO]?[0-7]+(_[0-7]+)*
binary : 0[bB][01]+(_[01]+)*
integer : decimal
| hexadecimal
| octal
| binary
int의 크기는 플랫폼에 따라 달라요. 보통은 약 20억(32비트 부호 있는 정수)이 최댓값이고, 64비트 플랫폼에서는 약 9E18이 최댓값이에요. PHP는 부호 없는 정수(unsigned int)를 지원하지 않아요. 정수 크기는 상수 PHP_INT_SIZE로, 최댓값은 PHP_INT_MAX, 최솟값은 PHP_INT_MIN으로 확인할 수 있어요.
정수 오버플로 (Integer overflow)
PHP가 int 타입의 범위를 벗어난 수를 만나면, 그 수를 float로 해석해요. 또 연산 결과가 int 범위를 넘어서면 그 결과도 float로 돌아와요.
예제 #2 정수 오버플로
<?php
$large_number = 50000000000000000000;
var_dump($large_number); // float(5.0E+19)
var_dump(PHP_INT_MAX + 1); // 32-bit system: float(2147483648)
// 64-bit system: float(9.2233720368548E+18)
?>
정수 나눗셈 (Integer division)
PHP에는 정수 나눗셈 전용 연산자가 없어요. 정수 나눗셈이 필요하다면 intdiv() 함수를 쓰면 돼요. 예를 들어 1/2는 float 0.5가 돼요. 값을 (int)로 캐스팅하면 0 쪽으로 버림(round towards zero)을 하고, round() 함수를 쓰면 더 세밀하게 반올림을 제어할 수 있어요.
예제 #3 나눗셈
<?php
var_dump(25/7); // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7)); // float(4)
?>
정수로 변환하기 (Converting to integer)
값을 명시적으로 정수로 바꾸려면 (int) 캐스트를 쓰면 돼요. 다만 대부분의 경우 캐스트 없이도 괜찮아요. 연산자, 함수, 제어 구조가 int 인자를 요구하면 값이 자동으로 변환되거든요. intval() 함수로도 정수로 바꿀 수 있어요.
resource를 int로 변환하면, PHP가 실행 시점에 그 리소스에 부여한 고유한 리소스 번호가 결과가 돼요.
타입 변환 전반에 대해서는 타입 저글링(Type Juggling) 문서도 함께 보면 좋아요.
불리언에서 (From booleans)
불리언을 정수로 바꾸면 false는 0(영)이 되고, true는 1(일)이 돼요.
부동소수점에서 (From floating point numbers)
float를 int로 변환하면 0 쪽으로 버림을 해요. PHP 8.1.0부터는 정수가 아닌 float를 정수로 암시적 변환할 때 정밀도를 잃으면 Deprecated 경고가 발생해요.
예제 #4 부동소수점에서 캐스팅
<?php
function foo($value): int {
return $value;
}
var_dump(foo(8.1)); // "Deprecated: Implicit conversion from float 8.1 to int loses precision" as of PHP 8.1.0
var_dump(foo(8.1)); // 8 prior to PHP 8.1.0
var_dump(foo(8.0)); // 8 in both cases
var_dump((int) 8.1); // 8 in both cases
var_dump(intval(8.1)); // 8 in both cases
?>
float가 int의 경계를 벗어나면 결과는 정의되지 않아요. (32비트 플랫폼에서는 대략 ± 2.15e+9 = 2^31, 64비트 플랫폼에서는 대략 ± 9.22e+18 = 2^63이 경계예요.) float는 정확한 정수 결과를 줄 만큼의 정밀도를 갖고 있지 않기 때문이에요. PHP 8.5.0부터는 int로 표현할 수 없는 float를 캐스팅하면 E_WARNING이 발생하고, 그 이전 버전에서는 아무 진단도 나오지 않았어요.
참고:
NaN,Inf,-Inf는 정수로 캐스팅하면 항상0이 돼요. PHP 8.5.0부터는 이들을int로 캐스팅하면E_WARNING이 발생하며,NAN을 다른 타입으로 캐스팅할 때도 마찬가지로E_WARNING이 발생해요.
경고: 알 수 없는 분수를 정수로 캐스팅하지 마세요. 때로는 예상치 못한 결과가 나올 수 있어요.
<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>
왜 8이 아닌 7이 나오는지는 float의 정밀도에 대한 경고 문서도 함께 보면 이해가 쉬워요.
문자열에서 (From strings)
문자열이 숫자 문자열(numeric) 이거나 숫자로 시작하는 문자열(leading numeric) 이면 그에 해당하는 정수 값으로 변환돼요. 그렇지 않은 문자열은 0(영)으로 변환돼요.
NULL에서 (From NULL)
null은 항상 0(영)으로 변환돼요.
다른 타입에서 (From other types)
주의: 다른 타입을 정수로 변환하는 동작은 정의되어 있지 않아요. 관찰된 어떤 동작에도 의존하지 마세요. 예고 없이 바뀔 수 있으니까요.
같이 보기
- 부동소수점 (Floating-point numbers)
- 임의 정밀도 / BCMath (Arbitrary precision / BCMath)
- 임의 길이 정수 / GMP (Arbitrary length integer / GMP)