Mathematics7 min readExamples run on PHP 8.5.10

fdiv()

Learn how PHP fdiv() divides floats following IEEE 754 and returns INF, -INF or NAN for a zero divisor instead of throwing an error.

Signature

fdiv(float $num1, float $num2): float

Purpose

fdiv() divides one number by another and always gives back a float. Its defining trait is how it treats a zero divisor. The / operator throws DivisionByZeroError in that situation, but fdiv() follows the IEEE 754 floating point rules and returns a special value instead. You can then keep computing, or inspect the result, without wrapping the call in try/catch.

Signature

Parameters

  • num1: the dividend (the numerator).
  • num2: the divisor.

Neither parameter has a default, so both are required. Integers are accepted and converted to floats. In the default (non-strict) mode, numeric strings are coerced as well, but a non-numeric string raises a TypeError.

Return value and failure cases

The function returns the float result of num1 / num2. When num2 is zero, the result is one of three special values:

  • INF when the dividend is positive,
  • -INF when the dividend is negative,
  • NAN when the dividend is also zero.

The sign of a zero divisor matters too. Floats have a negative zero, so dividing a positive number by -0.0 yields -INF.

No exception is thrown for division by zero. The only failure you should expect is a TypeError for arguments that cannot be treated as numbers.

Example 1: ordinary division

With a non-zero divisor, fdiv() behaves like normal float division. Note that the result is a float even when the answer is a whole number.

Example
<?php
var_dump(fdiv(7, 2));
var_dump(fdiv(4, 2));
var_dump(fdiv(-9, 3));
Output
float(3.5)
float(2)
float(-3)

Example 2: dividing by zero

This is where fdiv() differs from the / operator. Each call below returns a value and none of them throws.

Example
<?php
var_dump(fdiv(1.0, 0.0));
var_dump(fdiv(-1.0, 0.0));
var_dump(fdiv(0.0, 0.0));
var_dump(fdiv(1.0, -0.0));
Output
float(INF)
float(-INF)
float(NAN)
float(-INF)

Example 3: turning special values into labels

Because the special results are ordinary floats, you can test them with is_nan() and is_infinite() and decide what to show to a user.

Example
<?php
function ratioLabel(float $a, float $b): string
{
    $r = fdiv($a, $b);
    if (is_nan($r)) {
        return 'undefined';
    }
    if (is_infinite($r)) {
        return $r > 0 ? 'positive infinity' : 'negative infinity';
    }
    return (string) $r;
}

echo ratioLabel(9, 4), "\n";
echo ratioLabel(5, 0), "\n";
echo ratioLabel(-5, 0), "\n";
echo ratioLabel(0, 0), "\n";
Output
2.25
positive infinity
negative infinity
undefined

Edge cases

  • NAN never equals anything. NAN == NAN and NAN === NAN are both false, so fdiv(0.0, 0.0) === NAN cannot detect the result. Use is_nan().
  • Infinity propagates. Adding to or multiplying INF by a positive number keeps it infinite, while mixing INF and -INF in addition can produce NAN. A single zero divisor early on can therefore contaminate a longer calculation.
  • Overflow follows IEEE 754 too. A quotient too large for a float can become infinite even though the divisor was not zero.
  • Negative zero. 0.0 and -0.0 compare equal, but they push the sign of an infinite result in opposite directions.
  • Float precision still applies. Results such as fdiv(1, 3) are approximations, so compare them with a tolerance rather than strict equality.

Common mistakes

  1. Expecting an exception. Developers sometimes use fdiv() and still write a catch (DivisionByZeroError) block. That handler will not run for this function.
  2. Comparing against NAN. As noted, equality checks cannot succeed. Always call is_nan().
  3. Assuming an integer result. fdiv(4, 2) is float(2), not int(2). If you need integer division, use intdiv(), which throws on a zero divisor.
  4. Printing without checking. Echoing the result gives strings like INF or NAN, which may be confusing in output meant for end users. Check first, then format.
  5. Hiding bugs. If a zero divisor means your data is invalid, the silent INF can let the bad value travel far from its origin. In that case the / operator's exception is the better tool.
  • The / division operator, which throws DivisionByZeroError for a zero divisor.
  • intdiv() for integer division.
  • fmod() for the floating point remainder.
  • is_nan(), is_infinite() and is_finite() for examining special float values.
  • fpow(), the IEEE 754 counterpart for exponentiation.

Recap

fdiv(float $num1, float $num2): float divides two numbers using IEEE 754 semantics. For a non-zero divisor you get the normal quotient as a float. For a zero divisor you get INF, -INF or NAN rather than an exception. Test those values with is_nan() and is_infinite(), and choose / instead when a zero divisor should be treated as an error.

Tested examples

Ordinary division always returns a float
<?php
var_dump(fdiv(7, 2));
var_dump(fdiv(4, 2));
var_dump(fdiv(-9, 3));
Output
float(3.5)
float(2)
float(-3)
Dividing by zero returns special values
<?php
var_dump(fdiv(1.0, 0.0));
var_dump(fdiv(-1.0, 0.0));
var_dump(fdiv(0.0, 0.0));
var_dump(fdiv(1.0, -0.0));
Output
float(INF)
float(-INF)
float(NAN)
float(-INF)
Turning special results into readable labels
<?php
function ratioLabel(float $a, float $b): string
{
    $r = fdiv($a, $b);
    if (is_nan($r)) {
        return 'undefined';
    }
    if (is_infinite($r)) {
        return $r > 0 ? 'positive infinity' : 'negative infinity';
    }
    return (string) $r;
}

echo ratioLabel(9, 4), "\n";
echo ratioLabel(5, 0), "\n";
echo ratioLabel(-5, 0), "\n";
echo ratioLabel(0, 0), "\n";
Output
2.25
positive infinity
negative infinity
undefined