整数

一个 int 是集合 ℤ = {..., -2, -1, 0, 1, 2, ...} 中的一个数。

语法

Int 可以用十进制(基数 10)、十六进制(基数 16)、八进制(基数 8)或二进制(基数 2)表示法指定。 否定运算符 可用于表示负 int

要使用八进制表示法,请在数字前面加上一个 0(零)。从 PHP 8.1.0 开始,八进制表示法也可以在前面加上 0o0O。要使用十六进制表示法,请在数字前面加上 0x。要使用二进制表示法,请在数字前面加上 0b

从 PHP 7.4.0 开始,整数字面量可以在数字之间包含下划线 (_),以提高字面量的可读性。这些下划线将被 PHP 的扫描器移除。

示例 #1 整数字面量

<?php
$a
= 1234; // 十进制数
$a = 0123; // 八进制数(等效于十进制的 83)
$a = 0o123; // 八进制数(从 PHP 8.1.0 开始)
$a = 0x1A; // 十六进制数(等效于十进制的 26)
$a = 0b11111111; // 二进制数(等效于十进制的 255)
$a = 1_234_567; // 十进制数(从 PHP 7.4.0 开始)
?>

形式上,int 字面量的结构从 PHP 8.1.0 开始(之前不允许使用 0o0O 八进制前缀,并且在 PHP 7.4.0 之前不允许使用下划线)

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 的大小与平台相关,尽管通常最大值为大约二十亿(即 32 位有符号)。64 位平台通常的最大值为大约 9E18。PHP 不支持无符号 int。可以使用常量 PHP_INT_SIZE 确定 int 的大小,可以使用常量 PHP_INT_MAX 确定最大值,可以使用常量 PHP_INT_MIN 确定最小值。

整数溢出

如果 PHP 遇到超出 int 类型范围的数字,它将被解释为 float。同样,导致超出 int 类型范围的数字的操作将返回 float

示例 #2 在 32 位系统上整数溢出

<?php
$large_number
= 2147483647;
var_dump($large_number); // int(2147483647)

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

$million = 1000000;
$large_number = 50000 * $million;
var_dump($large_number); // float(50000000000)
?>

示例 #3 在 64 位系统上整数溢出

<?php
$large_number
= 9223372036854775807;
var_dump($large_number); // int(9223372036854775807)

$large_number = 9223372036854775808;
var_dump($large_number); // float(9.2233720368548E+18)

$million = 1000000;
$large_number = 50000000000000 * $million;
var_dump($large_number); // float(5.0E+19)
?>

PHP 中没有 int 除法运算符,要实现此功能,请使用 intdiv() 函数。1/2 会产生 float 0.5。该值可以转换为 int 以将其舍入为零,或者 round() 函数可以更精确地控制舍入。

<?php
var_dump
(25/7); // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7)); // float(4)
?>

转换为整数

要将值显式转换为 int,请使用 (int)(integer) 强制转换。但是,在大多数情况下,不需要强制转换,因为如果运算符、函数或控制结构需要 int 参数,则该值将被自动转换。还可以使用 intval() 函数将值转换为 int

如果将 resource 转换为 int,则结果将是 PHP 在运行时分配给该 resource 的唯一资源号。

另请参见 类型转换

布尔值

false 将产生 0(零),而 true 将产生 1(一)。

浮点数

float 转换为 int 时,该数字将被舍入为零。从 PHP 8.1.0 开始,当将非整数 float 隐式转换为丢失精度的 int 时,会发出弃用通知。

<?php

function foo($value): int {
return
$value;
}

var_dump(foo(8.1)); // 从 PHP 8.1.0 开始,"Deprecated: Implicit conversion from float 8.1 to int loses precision"
var_dump(foo(8.1)); // PHP 8.1.0 之前为 8
var_dump(foo(8.0)); // 在两种情况下都为 8

var_dump((int)8.1); // 在两种情况下都为 8
var_dump(intval(8.1)); // 在两种情况下都为 8
?>

如果浮点数超过了 int 的边界(通常在 32 位平台上为 +/- 2.15e+9 = 2^31,在 64 位平台上为 +/- 9.22e+18 = 2^63),则结果是未定义的,因为 float 没有足够的精度来提供精确的 int 结果。在这种情况下,不会发出警告,甚至不会发出通知!

注意:

NaN 和 Infinity 在转换为 int 时始终为零。

警告

不要将未知分数转换为 int,因为这有时会导致意外结果。

<?php
echo (int) ( (0.1+0.7) * 10 ); // 回显 7!
?>

另请参阅关于浮点精度 警告

从字符串

如果字符串是 数值 或者以数值开头,那么它将解析为相应的整数值,否则它将转换为零 (0)。

NULL

null 始终转换为零 (0)。

从其他类型

注意

将其他类型转换为 int 的行为是未定义的。不要依赖任何观察到的行为,因为它们可能会在未经通知的情况下更改。

添加笔记

用户贡献笔记 11 notes

php at richardneill dot org
11 年前
数值字面量中的前导零表示“这是八进制”。但不要混淆:字符串中的前导零不是。因此
$x = 0123; // 83
$y = "0123" + 0 // 123
d_n at NOSPAM dot Loryx dot com
17 年前
以下是一些将“点分”IP 地址转换为 LONG int 的技巧,反之亦然。这非常有用,因为在数据库表中访问 IP 地址,如果将它存储为 BIGINT 而不是字符,会快得多。

IP 到 BIGINT
<?php
$ipArr
= explode('.',$_SERVER['REMOTE_ADDR']);
$ip = $ipArr[0] * 0x1000000
+ $ipArr[1] * 0x10000
+ $ipArr[2] * 0x100
+ $ipArr[3]
;
?>

从数据库中读取的 IP 作为 BIGINT 转换为点分形式

请记住,PHP 整数运算符是 INTEGER -- 而不是 long。此外,由于 PHP 中没有整数除法,因此通过位移操作,我们节省了几个 S-L-O-W floor(<division>)。我们必须对 $ipArr[0] 使用 floor(/),因为虽然 $ipVal 存储为 long 值,但 $ipVal >> 24 将对 $ipVal 的截断整数进行操作!但是,$ipVint 是一个很好的整数,所以
我们可以享受位移操作。

<?php
$ipVal
= $row['client_IP'];
$ipArr = array(0 =>
floor( $ipVal / 0x1000000) );
$ipVint = $ipVal-($ipArr[0]*0x1000000); // for clarity
$ipArr[1] = ($ipVint & 0xFF0000) >> 16;
$ipArr[2] = ($ipVint & 0xFF00 ) >> 8;
$ipArr[3] = $ipVint & 0xFF;
$ipDotted = implode('.', $ipArr);
?>
ganlvtech at qq dot com
4 年前
注意浮点数到整型转换的溢出

<?php

// 您可能期望这些
var_dump(0x7fffffffffffffff); // int(9223372036854775807)
var_dump(0x7fffffffffffffff + 1); // float(9.2233720368548E+18)
var_dump((int)(0x7fffffffffffffff + 1)); // int(9223372036854775807)
var_dump(0x7fffffffffffffff + 1 > 0); // bool(true)
var_dump((int)(0x7fffffffffffffff + 1) > 0); // bool(true)
var_dump((int)'9223372036854775807'); // int(9223372036854775807)
var_dump(9223372036854775808); // float(9.2233720368548E+18)
var_dump((int)'9223372036854775808'); // int(9223372036854775807)
var_dump((int)9223372036854775808); // int(9223372036854775807)

// 但实际上,它喜欢这些
var_dump(0x7fffffffffffffff); // int(9223372036854775807)
var_dump(0x7fffffffffffffff + 1); // float(9.2233720368548E+18)
var_dump((int)(0x7fffffffffffffff + 1)); // int(-9223372036854775808) <-----
var_dump(0x7fffffffffffffff + 1 > 0); // bool(true)
var_dump((int)(0x7fffffffffffffff + 1) > 0); // bool(false) <-----
var_dump((int)'9223372036854775807'); // int(9223372036854775807)
var_dump(9223372036854775808); // float(9.2233720368548E+18)
var_dump((int)'9223372036854775808'); // int(9223372036854775807)
var_dump((int)9223372036854775808); // int(-9223372036854775808) <-----

?>

当您尝试将它与零进行比较或从另一个值(例如金钱)中减去它时,这些溢出会很危险。
lewismoten at gmail dot com
1 个月前
关于“PHP 不支持无符号整数”部分,这在使用与 PHP_INT_MIN 匹配的有符号整数的硬编码最小值时,经常会导致很大的混淆。

<?php
// 64 位示例
var_dump(PHP_INT_MIN);
var_dump(-9223372036854775808);
var_dump(PHP_INT_MIN === -9223372036854775808);
// int(-9223372036854775808)
// float(-9.223372036854776E+18)
// bool(false)
?>

尽管在视觉上,我输入了与 PHP_INT_MIN 输出相同的数值 `-9223372036854775808`,但语言解析器只将其理解为两个表达式,其中一个否定运算符后跟 `9223372036854775808`。该值超过了整数的最大值,并被提升为浮点数。尽管过去曾建议建立一个钩子来专门查找此值,但这比看起来更难。标记器无法将否定运算符和整数评估为一个标记。此外,还需要处理二进制、八进制和十六进制字面量。

<?php
var_dump
(-9223372036854775808); // 字面量十进制
var_dump(-0x8000000000000000); // 字面量十六进制
var_dump(-0b1000000000000000000000000000000000000000000000000000000000000000); // 字面量二进制
var_dump(-01000000000000000000000); // 字面量八进制
?>

如果需要硬编码最小值,请使用 `PHP_INT_MIN`。它专门为此边缘情况而引入。另一种方法是编写 `-9223372036854775807 - 1`。
dhairya lakhera
6 年前
-------------------------------------------------------------------------
问题
var_dump((int) 010); // 输出 8

var_dump((int) "010"); // 输出 10

第一个是八进制表示法,所以输出是正确的。但是将 "010" 转换为整数时,它也应该输出 8 吗?
--------------------------------------------------------------------------
回答

使用 (int) 将值强制转换为整数始终会转换为默认基数,即 10。

以这种方式将字符串强制转换为数字不会考虑 PHP 中格式化整数值的多种方式(以 0 开头的表示 8 进制,以 "0x" 开头的表示 16 进制,以 "0b" 开头的表示 2 进制)。它只会查看字符串中的前几个字符并将其转换为 10 进制整数。前导零将被剥离,因为它们在数值中没有意义,因此您最终会得到 (int)"010" 的十进制值 10。

使用 (int)010 在基数之间转换整数时,将考虑格式化整数的各种方式。像 010 中的前导零表示该数字是八进制表示法,使用 (int)010 将将其转换为 10 进制的十进制值 8。

这类似于您如何使用 0x10 以十六进制 (16 进制) 表示法写入。使用 (int)0x10 将将其转换为 10 进制的十进制值 16,而使用 (int)"0x10" 最终将得到十进制值 0:由于 "x" 不是数值,因此后面的任何内容都将被忽略。

如果您想将字符串 "010" 解释为八进制值,则需要指示 PHP 执行此操作。intval("010", 8) 将解释该数字为 8 进制而不是默认的 10 进制,并且您最终将得到十进制值 8。您也可以使用 octdec("010") 将八进制字符串转换为十进制值 8。另一个选择是使用 base_convert("010", 8, 10) 明确地将数字 "010" 从 8 进制转换为 10 进制,但是此函数将返回字符串 "8" 而不是整数 8。

将字符串强制转换为整数遵循 intval 函数使用的相同逻辑

返回 var 的整数值,使用指定的基数进行转换(默认值为 10 进制)。
intval 允许指定不同的基数作为第二个参数,而直接强制转换操作则不,因此使用 (int) 始终会将字符串视为 10 进制。

php > var_export((int) "010");
10
php > var_export(intval("010"));
10
php > var_export(intval("010", 8));
8
egwayjen at gmail dot com
6 年前
"PHP 中没有整数除法运算符"。但从 PHP 7 开始,出现了 intdiv 函数。
Anonymous
17 年前
为了在某些函数中强制正确使用 32 位无符号整数,只需在处理它们之前添加 "+0"。

例如
echo(dechex("2724838310"));
将打印 '7FFFFFFF'
但它应该打印 'A269BBA6'

添加 "+0" 后,php 将正确处理 32 位无符号整数
正确地
echo(dechex("2724838310"+0));
将打印 'A269BBA6'
rustamabd@gmail-you-know-what
17 年前
使用大数的模运算时要小心,它会将浮点参数强制转换为整数,并可能返回错误结果。例如
<?php
$i
= 6887129852;
echo
"i=$i\n";
echo
"i%36=".($i%36)."\n";
echo
"alternative i%36=".($i-floor($i/36)*36)."\n";
?>
将输出
i=6.88713E+009
i%36=-24
alternative i%36=20
Anonymous
9 年前
仅当输入以数字开头时,转换为整数才有效
(int) "5txt" // 将输出整数 5
(int) "before5txt" // 将输出整数 0
(int) "53txt" // 将输出整数 53
(int) "53txt534text" // 将输出整数 53
litbai
8 年前
<?php
$ipArr
= explode('.', $ipString);
$ipVal = ($ipArr[0] << 24)
+ (
$ipArr[1] << 16)
+ (
$ipArr[2] << 8)
+
$ipArr[3]
;
?>
1. 位运算的优先级低于 '+', 所以应该使用括号。
2. PHP 中没有无符号整数,如果您使用的是 32 位版本,则当 IP 字符串的第一个位置大于 127 时,上面的代码将获得负结果。
3. 该代码实际上是计算 IP 字符串转换后的 32 位二进制位的整数值。
Jacek
17 年前
在 64 位机器上,最大整数值为 0x7fffffffffffffff (9 223 372 036 854 775 807)。
To Top