Written and maintained by CASRAI Editorial Board
Last updated
Rounding in R is done with round(x, digits = 0) for decimal places and signif(x, digits = 6) for significant digits. Both come with base R, and both follow a rule that surprises many first-time users: R’s own manual says that round(0.5) is 0 and round(-1.5) is -2, because exact halves go to the even digit rather than always upward. This guide explains that rule, why round(0.15, 1) cannot be trusted to give 0.2, and how rounding a stored value differs from only changing how it is displayed.
What rounding in R is used for in research
Researchers round values for two different reasons, and R keeps them apart. The first is to change the number itself, for example before computing a derived quantity or saving a cleaned data column. The second is to control how a result is printed in a table or a manuscript. round() and signif() do the first job. format() and sprintf() do the second. Mixing them up is the most common source of tables that look right but carry different numbers underneath. If you are reporting descriptive results, see summary statistics in R and standard deviation in R, where the values you will round are produced.
Install or access
All functions in this guide are in base R, so there is no package to install. R itself is distributed free from the Comprehensive R Archive Network (CRAN) at cran.r-project.org. The functions below are documented in the R manual pages “Round”, “format” and “sprintf”, listed under Sources.
Step-by-step: rounding in R
1. Round to a number of decimal places with round()
The usage in the manual is round(x, digits = 0, ...). The digits argument is, in the manual’s words, an “integer indicating the number of decimal places (round) or significant digits (signif) to be used.” The function works on a single number or on a whole vector at once.
round(123.456, 2) # 123.46
round(123.456) # 123
round(c(1.234, 5.678), 1) # 1.2 5.7
2. Round to the left of the decimal point with negative digits
A negative digits value rounds to a power of ten. The manual states: “Rounding to a negative number of digits means rounding to a power of ten.”
round(1234.567, -2) # 1200
round(1234.567, -3) # 1000
3. Round to significant digits with signif()
The usage is signif(x, digits = 6). The default of 6 means a call with no second argument keeps six significant digits. The manual gives the exact relationship between the two functions: signif(x, dig) is the same as round(x, dig - ceiling(log10(abs(x)))). That identity lets you derive one from the other. For 123456, ceiling(log10(123456)) is 6, so two significant digits means round(123456, 2 - 6), that is, round(123456, -4).
signif(123456, 2) # 120000
round(123456, -4) # 120000
4. Round up, down or toward zero with ceiling(), floor() and trunc()
These three are documented on the same manual page as round(). ceiling(x) returns the smallest integer not less than x, floor(x) returns the largest integer not greater than x, and trunc(x) truncates toward 0. The difference only shows on negative numbers.
ceiling(-2.7) # -2
floor(-2.7) # -3
trunc(-2.7) # -2
5. Control displayed decimals without changing the value
The format() function has the usage format(x, trim = FALSE, digits = NULL, nsmall = 0L, ...). Its nsmall argument is “the minimum number of digits to the right of the decimal point in formatting real/complex numbers in non-scientific formats”, and it is allowed between 0 and 20. The result is text, which is what you want for a table cell and not what you want for further arithmetic.
format(2, nsmall = 2) # "2.00"
Output and how to read it
Why does R round 0.5 to 0?
R follows the IEC 60559 standard, which the manual says is expected to be used, so a value sitting exactly on the boundary goes to the even digit. The manual’s own examples: round(0.5) is 0 and round(-1.5) is -2. So round(0.5) returns 0, round(1.5) and round(2.5) both go to even results (2 for each), and a column of half-values does not all drift upward. If your field convention is “round half up”, round() alone does not implement it.
Why can round(0.15, 1) be 0.1 or 0.2?
Because most decimal fractions are not stored exactly in binary. The manual says that “since e.g. 0.15 is not represented exactly” the rounding rule applies to the stored number, so round(0.15, 1) may not give the result the printed value suggests. What looks like a tie in decimal may sit just above or just below the boundary in the stored number, so you should not build a result on the assumption that a visible “5” in the last place will round a particular way.
Worked cross-walk: which function answers which question?
| You want | Use | Changes the stored value? |
|---|---|---|
| A fixed number of decimal places | round(x, digits) |
Yes |
| Rounding to tens, hundreds, thousands | round(x, -n) |
Yes |
| A fixed number of significant digits | signif(x, digits) |
Yes |
| The next integer up or down | ceiling(x), floor(x) |
Yes |
| Drop the fractional part toward zero | trunc(x) |
Yes |
| A minimum number of shown decimals | format(x, nsmall = n) |
No, returns text |
Troubleshooting
My value rounded the “wrong” way at 0.5, 1.5 or 2.5
This is the go-to-even rule described above, not an error. If a protocol or journal requires round-half-up, state the rule you applied and apply it explicitly rather than relying on the default.
A tie such as 0.15 gives a result I did not expect
This is the representation problem described above. The manual itself warns that the printed value and the stored number can differ. Rounding at the last step of a calculation, not at intermediate steps, keeps this from compounding. If you go on to run tests on the data, see running a t-test in R.
My table shows two decimals but the numbers behind it differ
If you used format() or sprintf(), only the text changed. The sprintf() manual page describes it as “a wrapper for the C function sprintf” and notes that fine details may depend on the platform, so do not assume that it breaks ties the same way as round(). When the rounded number must be reused in later calculations, use round() and keep the formatting for the final output step.
Free alternatives
Every option here is part of R itself, which is free software.
| Function | Documented purpose | Good for |
|---|---|---|
round(), signif() |
Round to decimal places or significant digits | Changing the value |
format() with nsmall |
Minimum digits right of the decimal point | Formatted text for tables |
sprintf() |
Wrapper for the C function sprintf; default precision for f is 6 decimal places |
Fixed-format strings, with platform-dependent fine details |
For keeping a rounding choice repeatable across a project, see computational reproducibility.
FAQ
How do I round to 2 decimal places in R?
Use round(x, 2). For example, round(123.456, 2) returns 123.46. To show two decimals as text, including a trailing zero, use format(x, nsmall = 2).
Does R round .5 up?
Not always. R follows IEC 60559 and goes to the even digit, so round(0.5) is 0 and round(-1.5) is -2.
What is the difference between round() and signif()?
round() counts decimal places, and signif() counts significant digits. They are linked by signif(x, dig) being the same as round(x, dig - ceiling(log10(abs(x)))).
How do I round to the nearest 10 or 100 in R?
Give round() a negative digits value: round(x, -1) for tens and round(x, -2) for hundreds.
How do I round up or down in R?
Use ceiling(x) to round up to an integer and floor(x) to round down. trunc(x) drops the fractional part toward zero.
Sources (official docs)
- R documentation, “Round” (round, signif, ceiling, floor, trunc), checked 2026-10-29: stat.ethz.ch/R-manual/R-devel/library/base/html/Round.html
- R documentation, “format”, checked 2026-10-29: stat.ethz.ch/R-manual/R-devel/library/base/html/format.html
- R documentation, “sprintf”, checked 2026-10-29: stat.ethz.ch/R-manual/R-devel/library/base/html/sprintf.html








