php round() 默认采用银行家舍入(四舍六入五成双),非传统四舍五入;正数如 round(2.5) 得 2,负数如 round(-2.5) 得 -2;需用 php_round_half_up 才实现严格四舍五入。

PHP round() 默认不是四舍五入?
不是默认不是,而是它确实是四舍五入——但只对「正数」看起来像你熟悉的四舍五入。负数时,round() 用的是「四舍六入五成双」(银行家舍入法)的变体,实际是向偶数舍入。比如 round(2.5) 得 2,round(3.5) 得 4;负数如 round(-2.5) 得 -2,不是 -3。
如果你要严格数学意义上的「正负都向上/向下/四舍五入到最近整数」,不能只靠默认行为。
-
round($x):默认精度 0,但遵循银行家舍入,不等于小学数学四舍五入 - 要强制传统四舍五入(即 0.5 永远进 1),得显式指定模式:
round($x, 0, PHP_ROUND_HALF_UP) -
PHP_ROUND_HALF_UP是 PHP 5.3+ 才有的常量,老环境需自己模拟
为什么 round(1.5) 有时返回 2,有时返回 1?
这通常不是 round() 本身的问题,而是浮点数精度导致的输入失真。比如 0.1 + 0.2 不等于 0.3,而是 0.30000000000000004。当你对类似 1.5 - 1e-16 这种「看起来是 1.5 实际略小」的数调用 round(),它就进了「舍」的分支。
- 用
var_dump($x)或sprintf('%.17f', $x)查真实值,别信 echo 输出 - 涉及金额、计数等敏感场景,优先用
int或字符串运算(如bcmul/bcadd),避免浮点参与舍入逻辑 - 临时补救:先
round($x, 10)抹掉尾部噪声,再round(..., 0, PHP_ROUND_HALF_UP)
round() 和 intval()、ceil()、floor() 的关键区别
它们根本不是一类操作:round() 是就近取整,其余三个是方向性截断或进位。混用会出逻辑漏洞,比如把 floor(2.9) 当作「四舍五入结果」就是错的。
立即学习“PHP免费学习笔记(深入)”;
-
intval(2.9)→2(直接截断小数,不四舍) -
floor(-2.1)→-3(向下取整,不是舍去小数) -
ceil(2.1)→3(向上取整,和 round 无关) - 只有
round($x, 0, PHP_ROUND_HALF_UP)才可靠实现「正负统一的四舍五入」
PHP 版本兼容与替代写法
PHP PHP_ROUND_HALF_UP 常量,直接写数字 1 会报错(因为常量未定义)。这时候要么升级,要么手写逻辑。
- 安全写法:
round($x + ($x >= 0 ? 0.5 : -0.5))—— 对正数加 0.5 再截断,负数减 0.5 再截断,模拟传统四舍五入 - 注意:该写法在极值(如
PHP_INT_MAX附近)可能溢出,普通业务数值没问题 - 如果项目已用
composer,可引入brick/math等库做确定性舍入,避免手写陷阱
浮点舍入看着简单,但一旦牵扯到钱、排序、分页计数,小数点后那点误差就会变成线上 bug。别省那行 PHP_ROUND_HALF_UP,也别信“看起来一样”。










