rguides

round()

round(x, digits = 0)

The round() function rounds numeric values to the specified number of decimal places. It uses round half to even (bankers rounding) by default, which reduces cumulative rounding errors in statistical computations.

Syntax

round(x, digits = 0)

Parameters

ParameterTypeDefaultDescription
xnumeric,A numeric vector or scalar to round
digitsinteger0Number of decimal places. Negative values round to powers of 10

Examples

Basic rounding

# Round to whole number
round(3.7)
# [1] 4

round(3.3)
# [1] 3

When the digits argument is omitted, round() defaults to zero decimal places and returns the nearest integer. The function uses banker’s rounding (round-half-to-even), so round(0.5) gives 0 and round(1.5) gives 2. This differs from the “round half up” convention taught in most introductory math courses, where 0.5 always rounds up to 1, and it is a common source of surprise for R users coming from other languages like Python.

Rounding to decimal places

# Round to 2 decimal places
round(3.14159, 2)
# [1] 3.14

round(2.675, 2)
# [1] 2.67

Floating-point representation explains why round(2.675, 2) returns 2.67 instead of the expected 2.68. The number 2.675 cannot be expressed exactly in binary floating point — the actual stored value is approximately 2.6749999999999998. Banker’s rounding then rounds this slightly-less-than-halfway value down to 2.67. For exact decimal arithmetic in financial applications, store amounts as integers of the smallest unit (cents) and divide only for display.

Rounding to powers of 10

# Round to nearest 10
round(123, digits = -1)
# [1] 120

# Round to nearest 100
round(1234, digits = -2)
# [1] 1200

Negative digits values are particularly useful for creating summary tables and reports where raw numbers are distractingly precise. round(x, -3) rounds to thousands, round(x, -6) rounds to millions. This produces cleaner axis labels in plots and more readable financial statements without changing the underlying data. The same negative-digits convention applies to signif(), which rounds to a specified number of significant figures rather than decimal places.

Working with vectors

x <- c(1.5, 2.5, 3.5, 4.5)
round(x)
# [1] 2 2 4 4

df <- data.frame(value = c(1.234, 5.678, 9.012))
df <- round(df, 2)
df
#   value
# 1  1.23
# 2  5.68
# 3  9.01

Applying round() to an entire data frame rounds every numeric column in one call, which is convenient for cleaning up display output. The function operates column by column, and non-numeric columns (factors, characters) are passed through unchanged. For selective rounding of specific columns, use dplyr::mutate(across(where(is.numeric), round, digits = 3)) to target only numeric variables while leaving others untouched.

Common patterns

Currency rounding

prices <- c(19.999, 29.999, 14.999)
round(prices, 2)
# [1] 19.99 29.99 14.99

Rounding prices to two decimal places is standard for currency display, but the banker’s rounding rule can produce unexpected results for values like 2.675 where floating-point representation issues combine with the round-half-to-even convention. For production financial code, consider using integer arithmetic (store amounts in cents) or the decimal package for exact decimal rounding that matches accounting conventions rather than IEEE 754 floating-point rules.

Normalizing measurements

readings <- c(1.23456, 7.89012, 3.45678)
round(readings, 3)
# [1] 1.235 7.890 3.457

round() and banker’s rounding

round() in R uses banker’s rounding (round-half-to-even) by default: values exactly halfway between two integers round to the nearest even number. So round(0.5) is 0, round(1.5) is 2, and round(2.5) is 2. This is different from the “round half up” rule most people learned in school.

Banker’s rounding reduces systematic bias in large datasets where many values fall exactly at the midpoint. For financial calculations that require traditional rounding, use round(x + .Machine$double.eps) as a workaround, or use the janitor package’s round_half_up() function.

The digits argument controls decimal places: round(x, 2) rounds to 2 decimal places, round(x, -2) rounds to the nearest 100. Negative digits values are useful for rounding to thousands or millions in reports.

round() returns a double even when the result is a whole number. To get integers, follow with as.integer() if the storage type matters.

round() behavior and edge cases

round() in R uses “round half to even” (banker’s rounding): when a value is exactly halfway between two integers, it rounds to the nearest even integer. round(0.5) returns 0, round(1.5) returns 2, round(2.5) returns 2, round(3.5) returns 4. This differs from the “round half up” rule used in most everyday contexts, where 0.5 would round to 1. Banker’s rounding is statistically unbiased, rounding up and down with equal frequency, but surprises users who expect the familiar rule.

The digits argument controls decimal places. Positive values round to that many decimal places: round(3.14159, 2) gives 3.14. Zero rounds to the nearest integer (the default). Negative values round to powers of ten: round(1234, -2) gives 1200, rounding to the nearest hundred. This is useful for rounding large numbers to a readable precision, for example in summary statistics or axis tick labels.

Floating-point representation can cause unexpected results: round(2.675, 2) returns 2.67 rather than 2.68 because 2.675 cannot be represented exactly in binary floating point — the stored value is slightly less than 2.675. For exact decimal rounding in financial calculations, use the decimal package or store amounts as integers (cents) and convert for display only.

For rounding down always, use floor(); for rounding up always, use ceiling(); for truncating toward zero (no rounding), use trunc(). These four functions cover all common rounding conventions and their behavior at the boundary values is deterministic and predictable.

Comparing rounding strategies on real data

# Exam scores with half-point values
scores <- c(72.5, 83.5, 64.5, 91.5, 78.5, 85.5)

# Default: banker's rounding (round half to even)
round(scores)
# [1] 72 84 64 92 78 86

# Traditional round-half-up: add a tiny offset to break ties upward
round(scores + sign(scores) * 1e-10)
# [1] 73 84 65 92 79 86

# Count how many rounded up vs down under each strategy
bankers_direction <- ifelse(round(scores) > scores, "up", "down")
table(bankers_direction)
# bankers_direction
# down   up
#    3    3

Banker’s rounding breaks ties toward the nearest even number, which means exactly half the .5 values round up and half round down in this balanced set. The offset trick scores + sign(scores) * 1e-10 nudges each value infinitesimally above the tie point, producing the traditional round-half-up behaviour that most non-statisticians expect. For large datasets where half-point values are rare, the difference between the two strategies is negligible, but for financial portfolios with thousands of daily transactions, the cumulative bias of always rounding .5 up can reach meaningful amounts over time.

See also