Mathematics7 min readExamples run on PHP 8.5.10

is_finite()

Learn how PHP 8.4 is_finite() tells ordinary floats apart from NAN, INF and -INF, with tested examples, edge cases and common mistakes.

Signature

is_finite(float $num): bool
Available since PHP 4.2.07.48.08.18.28.38.48.5All versions →

Purpose

is_finite() answers one question: is this number an ordinary, bounded float? PHP floats can hold three special kinds of value that are not ordinary numbers: NAN (not a number), INF (positive infinity) and -INF (negative infinity). is_finite() returns true for everything else and false for those three.

These special values usually appear after an operation that cannot produce a real result, such as taking the square root of a negative number or multiplying two very large floats. Checking with is_finite() before you store, display or accumulate a result keeps bad values from spreading through later calculations.

Signature

The function is available in PHP 8.4 as a normal built-in function with no namespace.

Parameters

  • $num: the value to test. It has no default, so it is required. The declared type is float, so integers are accepted and converted to float. Numeric strings are also accepted when strict typing is off.

Return value and failure cases

The function returns a bool:

  • true when $num is none of NAN, INF or -INF.
  • false when $num is any of those three.

It never returns anything else. The only way to make it fail is to pass an argument that cannot be used as a float, such as an array or a non-numeric string like "abc". That raises a TypeError. Passing null to this non-nullable parameter is deprecated in modern PHP, so avoid it and check for null yourself first.

Example 1: Classifying a list of floats

The first example runs ordinary numbers and the three special values through the function. Zero and negative numbers are perfectly finite.

Example
<?php
$values = [1.2345, 0.0, -42.5, NAN, INF, -INF];
$result = [];
foreach ($values as $value) {
    $result[] = is_finite($value);
}
echo json_encode($result), PHP_EOL;
Output
[true,true,true,false,false,false]

Example 2: Where non-finite values come from

This example shows common sources: overflow, an invalid square root and float division by zero with fdiv(). A very large value that still fits in a float, like 1e308, remains finite.

Example
<?php
$checks = [
    'overflow' => 1e308 * 2,
    'sqrt_negative' => sqrt(-1),
    'fdiv_zero' => fdiv(1, 0),
    'large_but_finite' => 1e308,
];
$report = [];
foreach ($checks as $label => $value) {
    $report[$label] = is_finite($value);
}
echo json_encode($report), PHP_EOL;
Output
{"overflow":false,"sqrt_negative":false,"fdiv_zero":false,"large_but_finite":true}

Example 3: Averaging only the usable numbers

Because is_finite() takes one argument and returns a boolean, it works directly as a callback for array_filter(). The helper below ignores bad values and returns null when nothing usable remains.

Example
<?php
function finiteAverage(array $numbers): ?float
{
    $finite = array_values(array_filter($numbers, 'is_finite'));
    if ($finite === []) {
        return null;
    }
    return array_sum($finite) / count($finite);
}

var_dump(finiteAverage([2, 4.0, INF, NAN, 6]));
var_dump(finiteAverage([INF, -INF, NAN]));
Output
float(4)
NULL

Edge cases

  • Integers: an int is converted to float, so is_finite(10) is true. Even PHP_INT_MAX + 1, which becomes a float, is finite.
  • Negative zero: -0.0 is finite.
  • Largest float: PHP_FLOAT_MAX is finite, but doubling it overflows to INF.
  • NAN comparisons: NAN is never equal to anything, including itself, so $x === NAN and $x == NAN cannot detect it. Use is_nan() or is_finite() instead.
  • Strict types: with declare(strict_types=1), integers are still accepted for a float parameter, but strings are rejected with a TypeError.

Common mistakes

  1. Treating false as "is NAN". A false result only means the value is NAN or infinite. If you must know which, call is_nan() or is_infinite() as well.
  2. Comparing against NAN with ==. This never works. Use a function.
  3. Passing non-numeric input. Validate strings and arrays before calling the function, or you will get a TypeError.
  4. Encoding unchecked floats as JSON. json_encode() cannot represent NAN or INF, so filter or replace those values first.
  5. Assuming division by zero returns a float value. The / operator throws DivisionByZeroError, while fdiv() returns INF, -INF or NAN. Only the latter produces something for is_finite() to reject.
  • is_nan() checks whether a float is NAN.
  • is_infinite() checks whether a float is INF or -INF.
  • fdiv() divides floats following IEEE rules, without throwing on a zero divisor.
  • is_float() checks the type of a value, not whether it is a usable number.

Recap

is_finite() accepts a float and returns true unless the value is NAN, INF or -INF. Use it to guard results of risky math, to filter arrays of measurements and to protect output such as JSON. When you need the specific reason a value is not finite, pair it with is_nan() or is_infinite().

Tested examples

Classifying ordinary and special floats
<?php
$values = [1.2345, 0.0, -42.5, NAN, INF, -INF];
$result = [];
foreach ($values as $value) {
    $result[] = is_finite($value);
}
echo json_encode($result), PHP_EOL;
Output
[true,true,true,false,false,false]
Sources of non-finite values
<?php
$checks = [
    'overflow' => 1e308 * 2,
    'sqrt_negative' => sqrt(-1),
    'fdiv_zero' => fdiv(1, 0),
    'large_but_finite' => 1e308,
];
$report = [];
foreach ($checks as $label => $value) {
    $report[$label] = is_finite($value);
}
echo json_encode($report), PHP_EOL;
Output
{"overflow":false,"sqrt_negative":false,"fdiv_zero":false,"large_but_finite":true}
Averaging only finite numbers with array_filter
<?php
function finiteAverage(array $numbers): ?float
{
    $finite = array_values(array_filter($numbers, 'is_finite'));
    if ($finite === []) {
        return null;
    }
    return array_sum($finite) / count($finite);
}

var_dump(finiteAverage([2, 4.0, INF, NAN, 6]));
var_dump(finiteAverage([INF, -INF, NAN]));
Output
float(4)
NULL