PHPArithmetic Operators

Arithmetic Operators

Arithmetic operators are the ones you already know from math class: addition, subtraction, multiplication, division, and their less obvious cousins, modulo and exponentiation. PHP performs arithmetic the way you would expect for the most part, but a few edge cases around division and mixed types are worth understanding before they surprise you in a real script.

The basic six

Arithmetic operators

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
13
7
30
3.3333333333333
1
1000

/ is normal division and, unlike some languages, does not truncate to an integer even when both operands are integers — it returns a float whenever the result is not a whole number. % is the modulo operator: it returns the remainder after dividing the left operand by the right one. ** raises the left operand to the power of the right one; it was added in PHP 5.6 and is the modern replacement for calling pow().

Type coercion in arithmetic

Arithmetic operators expect numbers, so when you hand them a string PHP tries to convert it to a number first. A string that starts with digits, like "10 apples", converts to 10 (with a deprecation notice in modern PHP versions), while a string with no leading numeric part, like "apples", converts to 0.

Numeric strings in arithmetic

PHP
<?php
$price = "19.99";
$quantity = "3";

$total = $price * $quantity; // 59.97, both strings coerced to numbers
var_dump($total);
float(59.97)
Pre-increment vs post-increment

++$x increases $x before its value is used in the surrounding expression, while $x++ uses the current value first and increases $x immediately after. The difference only matters when the increment happens inside another expression, such as an assignment or a function argument.

Pre vs post increment

PHP
<?php
$x = 5;
$y = ++$x; // $x becomes 6 first, then $y = 6
echo "x={$x} y={$y}\n";

$x = 5;
$y = $x++; // $y = 5 (old value), then $x becomes 6
echo "x={$x} y={$y}\n";
x=6 y=6
x=6 y=5

The same rule applies in reverse for --$x and $x--. Decrementing also has a quirky corner case: decrementing null leaves it as null (it does not become -1), while incrementing null turns it into 1.

Division, modulo, and zero

This is the part of arithmetic that trips people up most, because PHP's behavior differs between the operators. As of PHP 8.0, dividing by zero with the / operator no longer throws an exception — it emits a warning and returns INF, -INF, or NAN depending on the numerator. Modulo by zero (%) and intdiv() by zero, on the other hand, both throw a DivisionByZeroError, which is a real exception you must catch or let crash the script.

Division by zero in PHP 8

PHP
<?php
$result = 10 / 0; // Warning: Division by zero
var_dump($result); // float(INF)

try {
    $result = 10 % 0;
} catch (\DivisionByZeroError $e) {
    echo "Caught: " . $e->getMessage() . "\n";
}

try {
    $result = intdiv(10, 0);
} catch (\DivisionByZeroError $e) {
    echo "Caught: " . $e->getMessage() . "\n";
}
Warning: Division by zero in ... on line 2
float(INF)
Caught: Modulo by zero
Caught: Division by zero
Do not assume / by zero throws
It is easy to write a `try`/`catch` around ordinary division expecting a `DivisionByZeroError`, copy the same pattern from `intdiv()` or `%`, and have it silently do nothing useful — `/` by zero does not throw in PHP 8, it warns and returns `INF`/`NAN`. If you need division to fail loudly, check the divisor yourself or use `intdiv()` and catch the error it raises.
intdiv() for integer division

When you specifically want integer division that truncates toward zero instead of returning a float, use intdiv() rather than / followed by a cast. It is clearer to read and it is the function that actually throws when the divisor is zero.

intdiv vs / with (int) cast

PHP
<?php
echo intdiv(10, 3), "\n";      // 3
echo (int) (10 / 3), "\n";    // 3, but less explicit about intent
echo intdiv(-10, 3), "\n";    // -3, truncates toward zero
  • + - * / % ** are the six arithmetic operators.

  • / always allows a float result; it never silently truncates.

  • % and intdiv() throw DivisionByZeroError when the divisor is 0.

  • / by zero only warns and returns INF, -INF, or NAN.

  • ++/-- before the variable act before the expression is evaluated; after the variable, they act after.

Floating-point precision
Because PHP stores floats using standard binary floating-point representation, results like `0.1 + 0.2` do not equal `0.3` exactly. Never compare floats with `==`; instead check whether the difference is smaller than an acceptable tolerance, or use arbitrary-precision functions such as `bcadd()` for money.
Tip
If a divisor could realistically be zero (user input, a computed average, a percentage), guard it explicitly with an `if` before dividing rather than relying on catching a warning or an error — it keeps the control flow obvious to the next person reading the code.