Signature
floor(int|float $num): floatPurpose
floor() rounds a number down to the nearest whole value that is not greater than the input. Any fractional part is dropped in the direction of negative infinity. This makes it useful for bucketing values, computing whole units already completed, or snapping a coordinate to a grid cell.
Signature
Parameters and defaults
$num is the only parameter, and it has no default. It accepts an integer or a float. In PHP's default weak typing mode, a numeric string such as "4.7" is converted to a number first. Under declare(strict_types=1), a string argument is rejected.
Since PHP 8.0.0, floor() no longer accepts internal objects that support numeric conversion. Pass a real number instead.
Return value and failure cases
The function returns the next lowest whole number, and the result is always of type float, even when the input was an int. A call such as floor(5) gives 5.0, which echo prints as 5.
Failures follow the usual rules for internal functions:
- A non-numeric string or an array raises a
TypeError. - Passing
nullto this non-nullable parameter is deprecated, so avoid it. NANand infinite values are not meaningful to round, and they come back as they are.
Example 1: positive and negative inputs
The key point is that rounding goes toward negative infinity. Positive fractions lose their decimals, but negative fractions move to the more negative whole number.
echo floor(4.3), PHP_EOL;
echo floor(9.999), PHP_EOL;
echo floor(-3.14), PHP_EOL;4 9 -4
The output is 4, 9 and -4. This differs from truncation, which would turn -3.14 into -3.
Example 2: the result is a float
Because the return type is float, you may need a cast if the next step expects an integer, for example an array index or a strictly typed parameter.
$value = floor(7.9);
var_dump($value);
var_dump((int) $value);float(7) int(7)
The first dump shows float(7) and the second shows int(7). Casting is safe here because the value is already whole and within the integer range.
Example 3: grouping values into buckets
Dividing by a bucket size, flooring and multiplying back gives the start of the bucket that contains a value. This works for age ranges, price bands or time slots measured in plain integers.
function bucketStart(int $value, int $size): int {
return (int) (floor($value / $size) * $size);
}
echo bucketStart(37, 10), PHP_EOL;
echo bucketStart(40, 10), PHP_EOL;
echo bucketStart(-3, 10), PHP_EOL;30 40 -10
The results are 30, 40 and -10. The negative case lands in the bucket that starts at -10 because floor() rounds toward negative infinity, which is usually what you want for consistent, gap-free buckets.
Edge cases
- Already whole numbers are returned unchanged, only as a float.
- Negative fractions move away from zero. For example,
-0.5becomes-1. - Very large floats are usually already whole numbers, since a float has limited precision. Flooring them changes nothing, and casting them to
intmay overflow the integer range. - Binary floating-point error can affect the input before
floor()sees it. A calculation that should give exactly8may produce7.999999999999999, and flooring it gives7. When exact decimal results matter, use integers, such as cents instead of dollars, or round to a sensible precision first.
Common mistakes
- Expecting an integer type. The result is a float. Cast it, or use integer division with
intdiv()when both operands are integers. - Confusing floor with truncation. For negative numbers the two differ, so check which behavior your logic needs.
- Using floor when rounding to nearest is intended.
floor(2.9)is2, whereasround(2.9)is3. - Flooring money calculated with floats. Tiny representation errors can drop a whole unit unexpectedly.
- Passing unvalidated input. Text that is not numeric causes a
TypeError, so validate user data before using it.
Related functions
ceil()rounds fractions up to the next highest whole number.round()rounds to the nearest value, with optional precision.intdiv()performs integer division directly.
Recap
floor() takes an int or float and returns the largest whole number not above it, always typed as float. Remember that negative values move toward negative infinity, cast the result when an integer is required, and be careful with floating-point input that is slightly below the value you expect.
Tested examples
echo floor(4.3), PHP_EOL;
echo floor(9.999), PHP_EOL;
echo floor(-3.14), PHP_EOL;4 9 -4
$value = floor(7.9);
var_dump($value);
var_dump((int) $value);float(7) int(7)
function bucketStart(int $value, int $size): int {
return (int) (floor($value / $size) * $size);
}
echo bucketStart(37, 10), PHP_EOL;
echo bucketStart(40, 10), PHP_EOL;
echo bucketStart(-3, 10), PHP_EOL;30 40 -10