Mathematics7 min readExamples run on PHP 8.5.10

ceil()

Learn how PHP 8.4 ceil() rounds numbers up to the next whole value, why it returns a float, and how to avoid common rounding mistakes.

Signature

ceil(int|float $num): float

Purpose

ceil() rounds a number up toward positive infinity until it reaches a whole value. If the input is already whole, it is returned unchanged. The name comes from "ceiling": the result is never lower than the input.

Typical uses are counting how many containers, pages or batches you need to hold a given number of items. In those cases a partial remainder still requires one more full unit.

Signature

Parameters and defaults

  • $num: the value to round. It can be an int or a float. There are no other parameters and no default values.

In the default (non-strict) typing mode, a numeric string such as "4.2" is converted to a number first. With declare(strict_types=1) only real integers and floats are accepted. Since PHP 8.0, ceil() no longer accepts internal objects that support numeric conversion.

Return value and failure cases

ceil() always returns a float, even when you pass an integer and the result is a whole number. The manual explains why: the range of a float is usually larger than that of an int, so the result could not always fit in an integer.

There is no false return value. Instead, bad input is handled by PHP's type system. A non-numeric string such as "abc" raises a TypeError. Special float values pass through: INF stays infinite and NAN stays NAN.

Example 1: the basic behavior

Positive fractions go up to the next integer. Negative fractions move toward zero, because zero is higher than a negative number.

Example
<?php
echo ceil(4.3), PHP_EOL;
echo ceil(9.999), PHP_EOL;
echo ceil(-3.14), PHP_EOL;
Output
5
10
-3

The -3.14 case surprises some people. The next highest integer above -3.14 is -3, not -4.

Example 2: counting containers

The division operator / can produce a fraction. Wrapping it in ceil() and casting to int gives a whole number of boxes.

Example
<?php
function boxesNeeded(int $items, int $perBox): int
{
    return (int) ceil($items / $perBox);
}

echo boxesNeeded(25, 10), PHP_EOL;
echo boxesNeeded(30, 10), PHP_EOL;
echo boxesNeeded(0, 10), PHP_EOL;
Output
3
3
0

Twenty-five items need three boxes, while thirty fit exactly into three. The explicit (int) cast is safe here because the values are small. If you need an integer type, convert the float yourself.

Example 3: float types, negative zero and rounding up to decimals

Example
<?php
var_dump(ceil(5));
var_dump(ceil(-0.5));
var_dump(ceil(2.0000001));
echo ceil(1.234 * 100) / 100, PHP_EOL;
Output
float(5)
float(-0)
float(3)
1.24

The first line shows that an integer input still produces a float. The second shows that rounding -0.5 up gives negative zero, which var_dump() prints as float(-0). In arithmetic it behaves like zero, but it can look odd if you print it directly. The last line uses a common trick to round up to two decimals: multiply, apply ceil(), then divide.

Edge cases

  • Whole numbers are returned unchanged, apart from becoming floats.
  • Tiny fractions still round up. A value like 2.0000001 becomes 3.
  • Negative values between -1 and 0 become negative zero (-0).
  • Very large floats are already whole numbers, so they come back unchanged. Casting them to int may overflow, so be careful with the cast.
  • Binary floating-point error can push a value just over a whole number. A result that looks like 3 on paper may be stored as 3.0000000000000004, and ceil() then returns 4. This is common after repeated multiplication or addition of decimals such as prices.
  • Null passed to this non-nullable parameter is deprecated in modern PHP. Avoid it by validating input first.

Common mistakes

  1. Expecting an integer type. Code that compares with === against an int will fail, because ceil(5) === 5 is false. Cast the result or compare with == if appropriate.
  2. Confusing it with round(). round() goes to the nearest value, whereas ceil() always goes up. ceil(4.1) is 5, but round(4.1) is 4.
  3. Forgetting negative direction. ceil(-2.5) is -2. If you want to round away from zero, you need extra logic.
  4. Integer division assumption. Writing ceil(intdiv(25, 10)) is pointless, because intdiv() has already discarded the fraction. Use the / operator inside ceil().
  5. Using floats for money. Rounding currency up after floating arithmetic can give off-by-one-cent results. Prefer storing minor units as integers.
  • floor() rounds fractions down, toward negative infinity.
  • round() rounds to the nearest value and supports a precision argument.
  • intdiv() performs integer division and discards the remainder.
  • fmod() returns the floating-point remainder of a division.

Recap

ceil(int|float $num): float rounds up to the next whole value and always returns a float. Positive fractions increase, negative fractions move toward zero, and whole numbers stay the same. Cast to int when you need an integer, and watch out for floating-point error before relying on exact results.

Tested examples

Basic rounding up
<?php
echo ceil(4.3), PHP_EOL;
echo ceil(9.999), PHP_EOL;
echo ceil(-3.14), PHP_EOL;
Output
5
10
-3
Counting containers
<?php
function boxesNeeded(int $items, int $perBox): int
{
    return (int) ceil($items / $perBox);
}

echo boxesNeeded(25, 10), PHP_EOL;
echo boxesNeeded(30, 10), PHP_EOL;
echo boxesNeeded(0, 10), PHP_EOL;
Output
3
3
0
Float types, negative zero and decimals
<?php
var_dump(ceil(5));
var_dump(ceil(-0.5));
var_dump(ceil(2.0000001));
echo ceil(1.234 * 100) / 100, PHP_EOL;
Output
float(5)
float(-0)
float(3)
1.24