Mathematics7 min readExamples run on PHP 8.5.10

fmod()

Learn how PHP 8.4 fmod() returns the floating-point remainder of a division, how the sign is chosen, and what happens with a zero divisor.

Signature

fmod(float $num1, float $num2): float
Available since PHP 4.2.07.48.08.18.28.38.48.5All versions →

Purpose

fmod() gives you the remainder left over when one floating-point number is divided by another. It is the float counterpart of the % operator. Use it when the values can have a fractional part, for example when wrapping an angle, folding a measurement into a repeating range, or checking how much is left after fitting whole units into a length.

The result r satisfies num1 = i * num2 + r for some whole number i. When the divisor is not zero, r carries the same sign as the dividend and its magnitude is smaller than the magnitude of the divisor.

Signature

Parameters and defaults

  • num1: the dividend, the number being divided.
  • num2: the divisor, the number you divide by.

Neither parameter has a default, so both are required. Integers are accepted and converted to floats when strict typing is off.

Return value and failure cases

The function always returns a float, even if the remainder looks like a whole number. If num2 is 0, the result is NAN (not a number). fmod() does not throw an exception for a zero divisor, so you need to check the result yourself with is_nan() if the divisor might be zero.

Example 1: the sign follows the dividend

The sign of the result comes from the first argument. The sign of the divisor does not change it.

Example
<?php
echo fmod(10, 3), "\n";
echo fmod(-10, 3), "\n";
echo fmod(10, -3), "\n";
echo fmod(-10, -3), "\n";
Output
1
-1
1
-1

This is the same rule the % operator follows, so negative values do not behave like a mathematical "always positive" modulo.

Example 2: fractions, zero and infinity

With 5.7 and 1.3, four whole divisors fit (4 × 1.3 = 5.2), leaving about 0.5. Because binary floats cannot store most decimals exactly, the raw value may differ from 0.5 in a far decimal place, so the example rounds it before printing.

Example
<?php
$r = fmod(5.7, 1.3);
echo round($r, 10), "\n";
var_dump(is_nan(fmod(5, 0)));
var_dump(fmod(5, INF));
Output
0.5
bool(true)
float(5)

A zero divisor produces NAN, which you detect with is_nan() rather than by comparing with ==. Dividing by infinity leaves the dividend unchanged, because no whole multiple of infinity fits into it.

Example 3: wrapping an angle

Because negative dividends give negative remainders, a wrapping helper usually needs one extra step to shift the result into the range 0 up to (but not including) 360.

Example
<?php
function normalizeDegrees(float $degrees): float {
    $result = fmod($degrees, 360.0);
    return $result < 0 ? $result + 360.0 : $result;
}

echo implode(",", [normalizeDegrees(450), normalizeDegrees(-90), normalizeDegrees(720)]), "\n";
Output
90,270,0

The value 450 wraps to 90, -90 wraps to 270, and 720 is exactly two full turns, which leaves 0.

Edge cases

  • Zero divisor: returns NAN, with no exception.
  • Dividend smaller than the divisor: the dividend comes back unchanged, since no whole multiple fits.
  • Exact multiples: the remainder is zero, returned as a float.
  • Precision: results are exact for the binary values stored, but those values may not match the decimal numbers you typed. Round before display or comparison.
  • Large magnitudes: very large floats lose fractional precision, so the remainder reflects the stored value, not your intended decimal.

Common mistakes

  1. Using % for fractional values. The % operator converts both operands to integers first, so 5.7 % 1.3 is treated as 5 % 1. It also throws DivisionByZeroError for a zero divisor, while fmod() returns NAN.
  2. Expecting a non-negative result. A negative dividend gives a negative remainder. Adjust it yourself if you need a positive range.
  3. Comparing floats with ==. A remainder such as 0.5000000000000004 will fail a strict equality test against 0.5. Use rounding or a small tolerance.
  4. Ignoring NAN. NAN is not equal to anything, including itself. Use is_nan().
  5. Assuming an integer result. The return type is always float, so use intdiv() or a cast if you need whole numbers.
  • intdiv() for integer division that discards the remainder.
  • fdiv() for floating-point division that does not throw on a zero divisor.
  • is_nan() to detect the failure value.
  • round(), floor() and abs() for tidying or adjusting remainders.
  • The % operator for integer remainders.

Recap

fmod(float $num1, float $num2): float returns the floating-point remainder of num1 / num2. The result takes the sign of num1, is smaller in magnitude than num2, and is NAN when num2 is zero. Reach for it when fractions matter, remember to correct negative results when wrapping, and round before you compare.

Tested examples

The sign of the result follows the dividend
<?php
echo fmod(10, 3), "\n";
echo fmod(-10, 3), "\n";
echo fmod(10, -3), "\n";
echo fmod(-10, -3), "\n";
Output
1
-1
1
-1
Fractions, zero divisor and infinity
<?php
$r = fmod(5.7, 1.3);
echo round($r, 10), "\n";
var_dump(is_nan(fmod(5, 0)));
var_dump(fmod(5, INF));
Output
0.5
bool(true)
float(5)
Wrapping an angle into 0 to 360
<?php
function normalizeDegrees(float $degrees): float {
    $result = fmod($degrees, 360.0);
    return $result < 0 ? $result + 360.0 : $result;
}

echo implode(",", [normalizeDegrees(450), normalizeDegrees(-90), normalizeDegrees(720)]), "\n";
Output
90,270,0