floor()
floor(x) floor() rounds numeric values down to the nearest integer, toward negative infinity. It’s part of R’s base package and essential for numerical computations requiring integer discretization.
Syntax
floor(x)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | numeric | , | A numeric vector to round down |
Technical details
The floor function follows the mathematical definition: for any real number x, floor(x) is the greatest integer less than or equal to x.
Key behaviors:
- Positive numbers: floor(3.7) returns 3 (moves left on number line)
- Negative numbers: floor(-2.3) returns -3 (moves left on number line, away from zero)
- Integers unchanged: floor(5) returns 5 (already an integer)
Examples
Basic usage with vectors
floor() is vectorized — pass a single number or a vector and it rounds every element down toward negative infinity. For positive values this matches the intuitive notion of “dropping the decimal,” but for negative values the behavior is less obvious: floor() always moves left on the number line.
# Positive numbers — drops the decimal
floor(3.7)
#> [1] 3
# Vector input — each element rounded independently
floor(c(1.1, 2.5, 3.9, 4.0))
#> [1] 1 2 3 4
Handling negative numbers
The convention of rounding toward negative infinity means floor(-1.5) returns -2, not -1. This is because -2 is the largest integer less than or equal to -1.5. The same logic extends to any negative non-integer: the result is always one more negative than the truncated value would be.
# Negative numbers move left on the number line
floor(-1.5)
#> [1] -2
# Compare multiple negative values
floor(c(-0.1, -3.7, -10.0))
#> [1] -1 -4 -10
Statistical binning
A common application of floor() is discretizing continuous data into bins. Dividing by the bin width, applying floor(), and multiplying back snaps each value to the lower boundary of its bin. This pattern computes histogram bins, age groups, or any equal-width categorical grouping without loading additional packages.
# Snap heights to 10-unit bins
heights <- c(162.3, 175.8, 183.2, 155.9, 168.7, 172.4, 180.1)
floor(heights / 10) * 10
#> [1] 160 170 180 150 160 170 180
# Create age groups from continuous ages
ages <- c(23.5, 34.2, 45.8, 19.9, 67.1, 52.3)
age_groups <- floor(ages / 10) * 10
age_groups
#> [1] 20 30 40 10 60 50
Integer division pattern
floor() underlies R’s integer division operator %/%. Both 7 %/% 3 and floor(7 / 3) return 2 — the quotient without the remainder. For positive numbers the two are identical, but for negative numbers %/% follows the same floor-based convention: -7 %/% 3 returns -3 because floor(-7/3) is -3. This pattern is vectorized, so you can apply it across entire columns.
# floor() and %/% are equivalent for integer division
7 %/% 3 #> [1] 2
floor(7 / 3) #> [1] 2
# Vectorized integer division with floor()
a <- c(17, 23, 31, 45)
b <- c(5, 4, 6, 7)
floor(a / b)
#> [1] 3 5 5 6
The %/% operator is a convenient shorthand, but using floor() directly makes the intent explicit — especially in code reviews where %/% might be mistaken for a modulo operator by developers coming from other languages. The vectorized form floor(a / b) works on vectors of any length and is equivalent to calling a %/% b for each pair of corresponding elements, provided both are numeric.
Common patterns
Ceiling comparison:
x <- 2.7
c(floor = floor(x), ceiling = ceiling(x), round = round(x))
#> floor ceiling round
#> 2 3 3
The side-by-side comparison of floor(), ceiling(), and round() on the same value 2.7 illustrates how each rounding function treats the fractional part differently. floor() drops the decimal, ceiling() goes up to the next integer, and round() picks the nearest integer according to the standard rounding rule. This three-way comparison is a quick way to confirm understanding of rounding conventions before applying them to a full dataset.
Data preprocessing — discretize continuous values:
values <- c(0.12, 0.55, 0.89, 0.34, 0.67)
floor(values * 5) # 5-level discretization
#> [1] 0 2 4 1 3
floor() vs ceiling() vs round() vs trunc()
floor() always rounds toward negative infinity, the floor of -2.3 is -3, not -2. This makes it suitable for computing lower bounds and bin indices in data analysis. When dividing a count into equal groups, floor(n / k) gives the number of items per group (with possible remainder).
Common uses for floor(): converting a continuous value to a bin index (floor(x / bin_width) gives which bin x falls into), extracting the day from a fractional number of days, and computing the integer part of a positive number. For negative numbers, floor() and trunc() diverge, choose based on whether you want rounding toward negative infinity (floor) or toward zero (trunc).
For data visualization, floor() and ceiling() are used to compute axis limits that extend slightly beyond the data range: floor(min(x)) and ceiling(max(x)) give clean integer bounds that contain all data points.
floor() is a C primitive and vectorized, it processes entire numeric vectors without loops.
floor() vs ceiling(), round(), and trunc()
floor() always rounds toward negative infinity — it returns the largest integer less than or equal to x. This means floor(-2.3) returns -3 (not -2), because -3 is the largest integer still less than -2.3. This distinguishes floor() from trunc(): trunc(-2.3) returns -2 (toward zero), while floor(-2.3) returns -3. For positive values, floor() and trunc() give the same result.
floor() is the basis for computing bin membership: floor(x / bin_width) maps a continuous value to the bin index it belongs to, and floor(x / bin_width) * bin_width snaps x to the lower bin boundary. These operations appear in histogram construction and in time series aggregation (e.g., rounding timestamps to the nearest hour by operating on POSIXct numeric values).
For modular arithmetic, x - floor(x / n) * n computes x mod n with the same sign convention as Python’s % operator (result always non-negative), while R’s x %% n already implements this. The two are equivalent for positive n and any x. Use floor() directly when you need the quotient in integer division while also keeping the remainder.
floor() is vectorized and propagates NA. It is faster than round() for cases where you always want the lower integer, because round() must check which integer is closer while floor() always goes down.