trunc()
trunc(x) The trunc() function truncates numeric values toward zero, removing the fractional part.
Syntax
trunc(x)
trunc() takes a single numeric argument — a scalar or a vector — and returns a vector of the same length with each element truncated toward zero. Unlike round(), which accepts a digits parameter for controlling precision, trunc() always strips the entire fractional part in one pass regardless of magnitude. The function is implemented as a C-level primitive and therefore handles large vectors efficiently with no R-level iteration overhead, making it suitable for high-throughput numerical pipelines.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | numeric | required | A numeric vector or scalar to truncate |
Examples
Basic usage
# Truncate positive numbers
trunc(3.14)
# [1] 3
trunc(3.99)
# [1] 3
Negative numbers
trunc() handles negative values by rounding toward zero rather than toward negative infinity. This means trunc(-2.7) returns -2, not -3. The sign of the result matches the sign of the input, and the fractional part is always simply discarded. This behavior distinguishes trunc() from floor(), which always rounds down regardless of sign.
# Truncate negative numbers (toward zero)
trunc(-2.7)
# [1] -2
trunc(-0.9)
# [1] 0
Comparison with floor and ceiling
Comparing trunc() against floor() and ceiling() on the same inputs clarifies when each function is appropriate. For positive values, trunc() and floor() agree because both effectively discard the fractional part. For negative values, however, trunc() rounds toward zero while floor() rounds toward negative infinity, producing different results for the same input.
x <- c(-2.5, -1.5, -0.5, 0.5, 1.5, 2.5)
floor(x)
# [1] -3 -2 -1 0 1 2
ceiling(x)
# [1] -2 -1 0 1 2 3
trunc(x)
# [1] -2 -1 0 0 1 2
Common patterns
Extracting integer part
Extracting the integer part with trunc() is a common operation in numerical workflows where only the whole-number portion matters. Unlike as.integer(), which converts the type and can overflow for large doubles, trunc() preserves the numeric type and simply zeros out the fractional component. The result remains a double, so subsequent floating-point operations work without type coercion surprises.
# Get integer part of a number
trunc(123.456)
# [1] 123
# Works with negative numbers too
trunc(-123.456)
# [1] -123
Date/time operations
trunc() also has a method for date-time objects, where it rounds a POSIXct or POSIXlt timestamp down to the specified unit. The unit argument accepts strings like "days", "hours", "mins", or "secs". This is distinct from round.POSIXt(), which rounds to the nearest unit rather than always downward. Use trunc() when you need the floor of a datetime for grouping or binning operations.
# Truncate POSIXct to date
dt <- as.POSIXct("2024-03-15 14:30:45")
trunc(dt, "days")
# [1] "2024-03-15"
# Truncate to hours
trunc(dt, "hours")
# [1] "2024-03-15 14:00:00"
Financial calculations
In financial contexts, trunc() strips cents from dollar amounts by removing the fractional part entirely, producing the integer-dollar component. This is not the same as rounding to the nearest dollar, which might inflate or deflate the total. When computing floor quantities such as whole shares of stock purchasable with a given cash balance, trunc() gives the correct integer count, whereas round() could overestimate.
# Integer dollars from decimal prices
prices <- c(10.99, 20.50, 5.01)
trunc(prices)
# [1] 10 20 5
trunc() vs floor() vs ceiling() vs round()
trunc() removes the fractional part by rounding toward zero, positive numbers round down, negative numbers round up (toward zero). floor() always rounds toward negative infinity, so floor(-2.3) is -3, but trunc(-2.3) is -2.
Use trunc() when you want to extract the integer part of a number regardless of sign, for example, computing the whole number of complete days from a fractional day count. Use floor() when you need the largest integer not exceeding the value, which is more useful in coordinate math and bin calculations.
round() rounds to the nearest integer (or specified number of decimal places) using banker’s rounding (round-half-to-even). None of these functions are interchangeable for negative values, so verify the rounding direction you need before choosing.
trunc() is implemented as a C primitive and is vectorized, it processes each element of a numeric vector independently. It propagates NA values unchanged. The function works on doubles and integers; for integer input, the result is always the same value (since integers have no fractional part). For complex numbers, trunc() is not defined and will error.
In financial and time calculations, trunc() is the right function when you need integer division behavior. trunc(7 / 2) gives 3 (the integer quotient), equivalent to the %/% operator, both produce the same result for positive numbers — for negative numbers they differ. For data binning into equal-width bins starting at zero, trunc(x / bin_width) gives the bin index directly. This is slightly different from using floor() for negative values: negative values would land in different bins depending on which function you use.
trunc() is the basis for integer division behavior in R: trunc(x / y) is equivalent to x %/% y for positive values, but they diverge for negative values. trunc(-7 / 2) gives -3 (toward zero), while -7 %/% 2 gives -4 (toward negative infinity, following the floor convention). Choose trunc() when you want symmetric behavior around zero, and %/% when you want consistent floor division.
Data binning with trunc()
# Assign ages to 10-year bins
ages <- c(23, 45, 67, 12, 38, 54, 29, 41)
bin_width <- 10
# Compute bin index: each bin covers [0,10), [10,20), etc.
bins <- trunc(ages / bin_width) * bin_width
data.frame(age = ages, bin_start = bins)
# age bin_start
# 1 23 20
# 2 45 40
# 3 67 60
# 4 12 10
# 5 38 30
# 6 54 50
# 7 29 20
# 8 41 40
# Count observations per bin
table(bins)
# bins
# 10 20 30 40 50 60
# 1 2 1 2 1 1
The expression trunc(x / bin_width) * bin_width maps every value to the left edge of its containing bin by stripping the fractional part after scaling. This approach is simpler than cut() for equally spaced numeric intervals and avoids creating factor levels, keeping the result numeric for further computation. The same pattern works for grouping timestamps by hour with trunc(dt, "hours") or for rounding financial amounts down to the nearest whole dollar before aggregation.