PHP 的算术运算符承担着数值计算的基础任务,从简单价格累加到复杂公式推导,几乎每个 PHP 程序都会用到。它们包括加、减、乘、除、取模以及 PHP 5.6 之后引入的幂运算。需要注意的是,PHP 属于弱类型语言,算术运算过程中会自动进行类型转换,这一特性在带来便利的同时,也容易产生一些隐蔽问题。尤其在涉及浮点数、字符串数字和优先级时,稍不留意就会得到与预期不符的结果。本文会从运算符类型、优先级规则、类型转换机制和实际场景四个角度展开,帮助你彻底理清用法。

一、PHP 算术运算符的类型与基本用法
PHP 一共提供了七种算术运算符,分别是加法 +、减法 -、乘法 *、除法 /、取模 %、幂运算 ** 以及取反 -(一元运算符)。其中取反运算符只作用于一个操作数,其余都是二元运算符。七种运算符中,加、减、乘、除与大多数编程语言一致,取模用于获取两个整数相除后的余数,幂运算则用于计算一个数的指定次方。下面用一段简单代码集中展示这些运算符的效果。
<?php $a = 10; $b = 3; echo $a + $b . "\n"; // 输出 13 echo $a - $b . "\n"; // 输出 7 echo $a * $b . "\n"; // 输出 30 echo $a / $b . "\n"; // 输出 3.3333333333333 echo $a % $b . "\n"; // 输出 1 echo $a ** $b . "\n"; // 输出 1000 echo -$a . "\n"; // 输出 -10
除法运算符 / 在 PHP 中总是返回浮点数,即使两个操作数能整除,例如 10 / 2 的结果是 float(5) 而不是 int(5)。这一点与某些语言不同,在进行严格类型比较时需要特别留意。取模运算符 % 在 PHP 8 之前要求操作数为整数,浮点数会先被转换为整数,这可能导致精度丢失;从 PHP 8 开始,浮点数取模会先取整部分再计算,行为更加明确。幂运算 ** 的底数和指数都可以是浮点数,例如 2 ** 0.5 可以得到 2 的平方根。
实际编码时,建议优先使用括号明确计算顺序,既方便阅读,也能避免因优先级理解偏差导致的逻辑错误。对于取模操作,如果参与运算的可能是浮点数,应先通过 intval() 或 round() 做显式转换,再执行取模。
二、算术运算符的优先级与结合方向
PHP 的运算符优先级决定了表达式中各运算的执行顺序。算术运算符内部,幂运算 ** 的优先级最高,其次是一元取反 -,然后是乘法、除法、取模,最后才是加法和减法。这意味着表达式 5 + 3 * 2 会先计算 3 * 2,再加上 5,结果是 11 而不是 16。如果想改变默认顺序,必须使用圆括号,例如 (5 + 3) * 2 才会得到 16。
<?php $result1 = 5 + 3 * 2; $result2 = (5 + 3) * 2; $result3 = 2 ** 3 ** 2; // 幂运算从右向左结合 echo $result1 . "\n"; // 输出 11 echo $result2 . "\n"; // 输出 16 echo $result3 . "\n"; // 输出 512,即 2 的 9 次方
结合方向也是容易忽略的点。加、减、乘、除、取模都是左结合,也就是说从左到右依次计算;而幂运算 ** 是右结合,2 ** 3 ** 2 会被解析为 2 ** (3 ** 2),而不是 (2 ** 3) ** 2。如果表达式中混合了多个不同优先级的运算符,建议拆分成多行代码或使用中间变量,这样代码的可读性和可维护性都会更好。
优先级问题在复杂的业务计算中经常出现。例如计算订单总价时,如果同时包含折扣和税费,直接写成 price * discount + tax 可能并不会按直觉先加后乘。养成使用括号的习惯,可以减少很多不必要的问题。
三、算术运算中的类型转换与常见陷阱
PHP 做算术运算时,如果操作数中包含字符串,会尝试将字符串转换为数字。例如 '10' + 5 的结果是 15,因为字符串 '10' 会被转换为整数 10。如果字符串不是合法的数字字符串,比如 'abc' + 5,PHP 会把它当作 0 处理,最终结果是 5。这种自动转换虽然方便,但也可能掩盖数据错误,导致计算偏差。
<?php $value1 = '10' + 5; $value2 = '10.5' + 2; $value3 = 'abc' + 5; echo $value1 . "\n"; // 输出 15 echo $value2 . "\n"; // 输出 12.5 echo $value3 . "\n"; // 输出 5
另一个典型问题是浮点数精度。十进制的小数在二进制中可能无法精确表示,例如 0.1 + 0.2 在 PHP 中并不会严格等于 0.3,而是得到一个类似 0.30000000000000004 的值。因此在涉及金额、库存等对精度要求较高的场景中,不能直接使用浮点数进行相等比较。更稳妥的做法是把金额转换成以分为单位的整数,或者使用 BC Math 扩展进行高精度计算。
<?php // 浮点精度问题 $sum = 0.1 + 0.2; echo $sum . "\n"; // 输出 0.3 但内部表示不精确 // 使用 BC Math 处理精度 $price = '19.99'; $quantity = '3'; echo bcmul($price, $quantity, 2) . "\n"; // 输出 59.97
除零操作也是初学者经常触发的错误。PHP 中整数除以零会触发 Division by zero 警告或异常,取模对零操作同样会报错。编写除法或取模代码前,应先判断除数是否为零。尤其在动态接收用户输入或接口数据时,这种防御性判断可以避免程序崩溃。
四、算术运算符在业务场景中的综合运用
在真实的 PHP 项目中,算术运算符很少单独出现,通常与变量、函数和条件判断组合在一起。例如分页功能中,需要根据总记录数和每页条数计算总页数,常见的写法是使用 ceil() 配合除法运算符。如果 total 为 101,perPage 为 10,那么总页数应为 11,直接相除得到 10.1,再向上取整即可。
<?php $total = 101; $perPage = 10; $pageCount = (int) ceil($total / $perPage); echo $pageCount . "\n"; // 输出 11
再比如电商促销活动中,需要根据原价和折扣计算最终支付金额。可以先通过乘法得到折扣金额,再用减法得到折后价。假设原价 258 元,打 7.5 折,最终价格等于 258 * 0.75。如果还要叠加优惠券,可以继续做减法操作。将这些步骤拆解为多个变量,不仅代码清晰,也方便后续调整规则。
<?php $originalPrice = 258; $discountRate = 0.75; $coupon = 20; $discountedPrice = $originalPrice * $discountRate; $finalPrice = $discountedPrice - $coupon; echo $finalPrice . "\n"; // 输出 173.5
总的来说,PHP 的算术运算符本身并不复杂,但由于弱类型和浮点数特性,实际使用中需要留意类型转换、精度和优先级。遇到复杂计算时,优先使用括号和中间变量,涉及金额时优先使用整数或高精度扩展,除法和取模前做好除数检查。掌握这些习惯,就能避免大部分因为算术运算符使用不当而引发的线上问题。