Skip to main content
v2026.11,858 entries · CC-BY 4.0

Rounding in R: round(), signif(), ceiling() and floor()

How rounding in R works: round(), signif(), negative digits, ceiling/floor/trunc, and why round(0.5) is 0 under IEC 60559.

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)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Rounding in R: round(), signif(), ceiling() and floor()

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.