Menu

PHP round()、floor() 和 ceil():取整与数学函数

round($x, 2) 保留两位小数,floor() 总是向下取整,ceil() 总是向上取整。另外还介绍 intdiv()、% 运算符、用于求幂的 **、abs()、max()、min(),以及生成随机数的 random_int()。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

round($x) 四舍五入到最接近的整数,floor($x) 总是向下取整,ceil($x) 总是向上取整。给 round() 传入第二个参数可以指定小数位数:round(3.14159, 2) 是 3.14。

这三个函数都返回浮点数,即使值是整数也一样。var_dump(round(5)) 打印 float(5),所以需要整数时用 (int) 转换。

保留两位小数

round() 的第二个参数是精度。正数表示四舍五入到相应的小数位数。负数表示在小数点左边取整,这在表示“大约 1,200 名访客”这样的粗略数字时很方便。

round(3.10, 2) 打印 3.1,因为浮点数并不知道你想要几个零。当数字要显示在页面上时(价格、百分比),应该对它进行格式化:number_format() 中的 number_format(3.1, 2) 会把 3.1 变成 "3.10",sprintf('%.2f', $x) 也能做到。

舍入模式:半数向上、向下或取偶

默认情况下,round() 把正好一半的值朝远离零的方向舍入,也就是大多数人在学校学的四舍五入。第三个参数可以为正好处于两个数中间的值选择另一种规则。

PHP_ROUND_HALF_EVEN 就是“银行家舍入法”:一半的值会舍入到最近的偶数,所以对大量数值取整时,结果不会随着时间推移而整体偏大。会计相关的代码通常需要它。

负数的 floor 和 ceil

floor() 朝负无穷方向取整,ceil() 朝正无穷方向取整。遇到负数时这常常让人意外:floor(-3.5) 是 -4,而不是 -3。如果你只是想截掉小数(朝零的方向截断),请转换为 int。

分页那一行是 ceil() 的经典用法:哪怕只多出一项,也需要再多一页。

整数除法和取余

除不尽时 / 返回浮点数,所以 7 / 2 是 3.5。要做整数除法,请使用会丢弃余数的 intdiv(),余数本身则用 % 求得。

% 会先把两个操作数都转换为整数,所以 7.5 % 2 是 1,而且从 PHP 8.1 开始还会打印 Deprecated: Implicit conversion from float 7.5 to int loses precision。小数部分有意义时请使用 fmod()。在 PHP 8 中,用 /、intdiv() 或 % 除以零都会抛出 DivisionByZeroError,所以当除数来自输入时,要先检查它。

求幂、开方、abs、max 和 min

** 用于求幂(pow() 的作用相同),sqrt() 求平方根,abs() 去掉符号。max() 和 min() 既可以接受多个参数,也可以接受一个数组。

** 从右向左求值,所以 2 ** 3 ** 2 的意思是 2 ** 9。max(0, min(100, $x)) 这一对组合是把值限制在上下限之间的常用写法。如果计算圆需要用到圆周率,M_PI 保存的就是它。

用 random_int 和 rand 生成随机数

random_int($min, $max) 返回一个包含两端的随机整数。每次运行的输出都不同,所以多按几次“运行”试试。

凡是与安全相关的场景都使用 random_int():登录验证码、令牌、重置密码的链接。rand() 和 mt_rand() 仍然可用,也接受同样的 ($min, $max) 参数,但它们生成的序列可以被预测。如果需要用安全的随机源来打乱和抽取元素,PHP 8.2 新增了 Random\Randomizer($r->getInt(1, 6)、$r->shuffleArray($a))。

为什么 floor() 有时会给出错误的答案

浮点数以二进制存储,许多十进制数值(例如 0.1)无法被精确存储。大多数时候打印会掩盖这一点,但 floor() 和 (int) 不做舍入,而是直接截断,于是像 7.999999999 这样的值就变成了 7。

需要精确的小数时(例如处理金额),用最小单位存储整数(以分为单位:用 1999 而不是 19.99),只在显示时才做除法。像最后一行那样,在 floor() 或 ceil() 之前先舍入到合理的精度,也能解决大多数情况。

常见问题

PHP 中怎么保留两位小数?

把小数位数作为第二个参数传入:round(3.14159, 2) 返回 3.14。它返回的是浮点数,所以如果要以固定的小数位数显示(3.10 而不是 3.1),请使用 number_format($x, 2) 或 sprintf('%.2f', $x)。

PHP 中怎么向下取整?

floor($x) 向下取到更小的整数:floor(4.9) 是 4,floor(-4.1) 是 -5。如果想朝零的方向直接去掉小数,就用 (int) $x 转换,它会把 -4.9 变成 -4。

PHP 中 round() 为什么返回浮点数?

round()、floor() 和 ceil() 总是返回浮点数,即使结果是整数也一样:var_dump(round(5)) 打印 float(5)。需要整数时(例如用作数组索引),用 (int) 或 intval() 包住这次调用。

PHP 中 rand() 和 random_int() 有什么区别?

random_int(1, 6) 使用密码学安全的随机源,生成令牌、验证码以及任何用户可能尝试猜测的东西时都应该用它。rand() 和 mt_rand() 更快,但可以被预测。这三个函数都包含范围的两端。

PHP 中怎么求除法的余数?

整数用 % 运算符:17 % 5 是 2。结果的符号与左操作数相同,所以 -7 % 3 是 -1。浮点数用 fmod(7.5, 2),它返回 1.5。

Coddy 编程语言插图

和 Coddy 一起学编程

开始