Short Answer
Give the same number, at the same halfway tie, to Excel, Python, R, and JavaScript, and you can get three genuinely different answers — not because any of them has a bug, but because they implement three different, individually correct rounding conventions. Underneath all of them sits the same root cause of most “why is my sig fig calculation wrong” software questions: binary floating-point numbers can’t represent most ordinary decimals exactly, which is also exactly why this site’s own calculator is built on an arbitrary-precision decimal library instead.
This is the last of the ten pillar guides on this site, and it’s the one that explains a question every other page has occasionally sidestepped: why does a calculator, a spreadsheet, or a script sometimes disagree with the rules taught elsewhere on this site? Two separate things are going on, and they get confused constantly. One is floating-point representation error — a genuine limitation of how computers store decimal numbers in binary. The other is which rounding convention a specific tool chose to implement — a design decision, not a bug, and one our rounding guide already showed varies even among the eight standard methods. This page covers both, tool by tool.
<!– BLOCK: B02 – Inline Mini-Calculator –> <!– DEV NOTE: Embed the main Significant Figures Calculator here, with a visible note in the UI: “This calculator uses an arbitrary-precision decimal engine, not native floating-point math — see why below.” Shortcode: [sfc_calculator mode=”mini” show_engine_note=”true”]. –>
[Live Significant Figures Calculator embeds here] — Built on an arbitrary-precision decimal engine specifically to avoid every issue on this page. See Example 1 for why that choice matters.
Two Separate Problems, Constantly Confused
Problem 1: floating-point representation error. Computers store numbers in binary, and most ordinary decimal fractions cannot be represented exactly in binary — only decimals whose fractional part is a finite sum of negative powers of two can (0.5, 0.25, 0.125, 0.75, and combinations of these). Everything else — 0.1, 0.2, 0.3, and the overwhelming majority of decimals anyone actually types — gets stored as the closest available binary approximation, not the exact value. This is why 0.1 + 0.2 famously displays as 0.30000000000000004 in most programming languages: neither 0.1 nor 0.2 was ever exactly 0.1 or 0.2 internally, and the tiny errors compound. This isn’t a flaw in any particular language — it’s inherent to IEEE 754 binary floating point, the format almost universally used to store decimal numbers in software.
Problem 2: different tools implement different rounding conventions, on purpose. Even without any representation error at all, tools genuinely disagree on what to do at an exact halfway tie — this is the same round-half-up vs. round-half-to-even distinction covered generally elsewhere on this site, just made concrete by specific software. Excel rounds ties away from zero. Python and R round ties to the nearest even digit. JavaScript rounds ties toward positive infinity — which, as Example 3 shows, is a third, distinct behavior from both of the others once negative numbers are involved.
The practical fix, and the one this site uses. Neither problem is solved by “being more careful” — it’s solved by not using native binary floating-point math for anything where the exact digit matters. Python’s decimal module, most spreadsheet-adjacent BigDecimal-style libraries, and this site’s own calculators all sidestep both problems by doing arithmetic in exact base-10 decimal instead of binary — which is exactly why the SignificantFiguresCalculator rule on this site requires every numeric tool to use an arbitrary-precision decimal engine rather than a language’s native float type.
Worked Examples
Example 1 — The 0.1 + 0.2 problem, and why it happens
In most languages, evaluating 0.1 + 0.2 returns 0.30000000000000004, not 0.3. Neither 0.1 nor 0.2 exists exactly in binary — each is stored as the nearest representable approximation, off by a tiny amount in the 17th significant digit or so. Adding two such approximations surfaces the error. A sig-fig calculator built on native floating point can silently produce a wrong final digit on results like this; one built on an exact decimal engine never encounters the problem, because it never converts the input to binary in the first place.
Example 2 — Rounding to significant figures in Excel
Excel’s native ROUND() function only rounds to a number of decimal places — it has no built-in “round to N significant figures” mode. The standard workaround combines ROUND() with LOG10() to first find the input’s order of magnitude:
=ROUND(value, sig_figs - 1 - INT(LOG10(ABS(value))))
Rounding 1234.567 to 3 significant figures: LOG10(1234.567) ≈ 3.09, INT(3.09) = 3. Sig figs (3) − 1 − 3 = −1. =ROUND(1234.567, -1) → 1230
Rounding 0.004567 to 2 significant figures: LOG10(0.004567) ≈ −2.34, INT(−2.34) = −3 (INT always rounds toward negative infinity, which is exactly what’s needed here). Sig figs (2) − 1 − (−3) = 4. =ROUND(0.004567, 4) → 0.0046
Both results are correct sig-fig roundings, confirmed independently. This same formula pattern works in Google Sheets without modification.
Example 3 — The same tie, five platforms, three different answers
Rounding 2.5 and −2.5 to the nearest integer:
| Platform | round(2.5) | round(−2.5) | Method |
|---|---|---|---|
Excel / Google Sheets ROUND() |
3 | −3 | Half away from zero |
Python round() |
2 | −2 | Half to even |
R round() |
2 | −2 | Half to even (IEC 60559) |
JavaScript Math.round() |
3 | −2 | Half toward positive infinity |
MATLAB round() |
3 | −3 | Half away from zero |
JavaScript is the outlier. It agrees with Excel on the positive case (3) but disagrees with everything else on the negative case, because it rounds every exact tie toward positive infinity rather than away from zero — matching the precise “round half up” definition from our rounding guide, not the more commonly assumed “away from zero” behavior most developers expect. MDN’s own documentation flags this explicitly as a difference from most other languages’ round() functions.
Example 4 — What R’s own documentation admits about representation error
R’s official manual for round() contains a specific, notable caveat: because 0.15 cannot be represented exactly in binary, round(0.15, 1) could return either 0.1 or 0.2, depending on which binary approximation of 0.15 the system actually stored — the rounding rule applies to the stored value, not the value as printed. This is Problem 1 (representation error) and Problem 2 (rounding convention) colliding in a single, officially-documented example: even knowing R uses round-half-to-even doesn’t fully predict the output, because the input itself might not be exactly what it looks like.
Example 5 — SQL engines don’t all agree either
A real 2026 compatibility issue in a SQLite-compatible database (Turso) surfaced exactly this problem: ROUND(2.25, 1) returned 2.2 (rounding to even) in one engine while SQLite itself returns a different result at the same tie, rounding away from zero instead. Database engines built to be “mostly compatible” with each other can still diverge at exactly the halfway point — the same lesson as Example 3, in a database context instead of a spreadsheet or scripting one.
Where This Still Trips People Up
- “My calculation is wrong” is often “my tool’s rounding convention differs from what I expected” — not a bug, and not something more careful arithmetic fixes. See Example 3.
- Floating-point error and rounding-convention differences are two separate problems that look identical from the outside. A wrong-looking last digit could be either one — Example 4 shows a case where they overlap.
- Assuming “round half away from zero” is the universal default is the single most common wrong assumption — it’s Excel’s behavior, but not Python’s, R’s, or (at the negative tie) even JavaScript’s.
- Porting a calculation between tools can silently change a result’s last digit at exactly the values where it matters most — a spreadsheet model rebuilt in Python, or vice versa, can disagree at ties without either implementation being wrong.
- The
decimalmodule (Python) or equivalent exact-arithmetic libraries exist precisely to sidestep Problem 1 — reaching for one is the fix when floating-point error, not rounding convention, is the actual issue.
How Six Platforms Round the Same Tie
| Platform | Tie-breaking method | Sig-fig rounding built in? |
|---|---|---|
| Excel / Google Sheets | Half away from zero | No — requires the LOG10 formula from Example 2 |
Python round() |
Half to even | No — round() rounds decimal places; sig figs need a small helper function |
Python decimal module |
Configurable (ROUND_HALF_UP, ROUND_HALF_EVEN, etc.) | No, but avoids floating-point error entirely |
R round() |
Half to even (IEC 60559), subject to representation error | No — signif() handles sig figs directly, unlike round() |
JavaScript Math.round() |
Half toward positive infinity | No — native JS has no sig-fig function at all |
MATLAB round() |
Half away from zero | Via round(x, n, 'significant') — MATLAB has native sig-fig support, unlike the others here |
R’s signif() function is worth calling out specifically: unlike round(), it’s designed for significant figures directly (signif(1234.567, 3) returns 1230 without any LOG10 workaround) — the one tool covered here that doesn’t need Example 2’s formula trick.
The Standard Underneath All of This
Nearly every general-purpose language’s floating-point behavior — including the round-half-to-even default in Python and R — traces back to IEEE 754 (equivalently, IEC 60559), the international standard defining binary floating-point arithmetic. It’s the same standard referenced in our rounding guide as the source of round-half-to-even’s status as a computing default. JavaScript’s departure from that default at the negative tie is a deliberate language-specification choice, not a deviation from IEEE 754 itself, which governs number storage rather than mandating one particular round() function’s tie-breaking behavior.
Common Mistakes
- Assuming a rounding discrepancy between two tools is a calculation error, when it’s very often just two different, individually valid conventions — see Example 3.
- Not knowing a language’s default tie-breaking rule before relying on it for anything where the last digit matters.
- Using native floating-point math for exact decimal work — currency, sig-fig calculators, anything where 0.1 + 0.2 needs to actually equal 0.3 — instead of an exact decimal type.
- Forgetting that Excel’s ROUND() rounds decimal places, not significant figures, and getting a wrong answer from a direct
ROUND(value, sig_figs)call. - Assuming R’s
round()is deterministic for values like 0.15 without accounting for representation error — see Example 4. - Porting a spreadsheet formula or script between platforms without checking tie-breaking behavior, and being surprised when a boundary case changes.
Practice Problems
Concept: Floating-point representation
Q1. Which of these can be represented exactly in binary floating point? A) 0.1 B) 0.3 C) 0.25 D) 0.7 Answer: C) 0.25 — it’s 2⁻², a finite sum of negative powers of two.
Q2. Why does 0.1 + 0.2 display as 0.30000000000000004 in most languages? A) It’s a language bug B) Both 0.1 and 0.2 are stored as imperfect binary approximations, and adding them surfaces the compounded error C) The language rounds down incorrectly D) This only happens in JavaScript Answer: B.
Concept: Excel’s sig-fig formula
Q3. What does =ROUND(1234.567, 3-1-INT(LOG10(ABS(1234.567)))) evaluate to? A) 1234.57 B) 1230 C) 1200 D) 1235 Answer: B) 1230.
Q4. Why doesn’t Excel’s ROUND() round to significant figures directly? A) It’s not possible in Excel B) ROUND() only takes a decimal-places argument, so LOG10() is needed to convert a sig-fig count into the right decimal-places value C) Excel doesn’t support sig figs at all D) It requires a paid add-in Answer: B.
Concept: Python and R’s banker’s rounding
Q5. What does Python’s round(2.5) return? A) 3 B) 2 C) 2.5 D) An error Answer: B) 2 — banker’s rounding.
Q6. R’s documentation warns round(0.15, 1) could return either 0.1 or 0.2. Why? A) R has a bug B) 0.15 isn’t exactly representable in binary, so rounding applies to whichever approximation was actually stored, not the printed value C) R rounds randomly D) It depends on the R version only Answer: B.
Concept: JavaScript’s distinct tie-breaking
Q7. What does JavaScript’s Math.round(-2.5) return? A) -3 B) -2 C) -2.5 D) An error Answer: B) -2 — rounds toward positive infinity, not away from zero.
Q8. How does Math.round()‘s rule at the negative tie differ from Excel’s and Python’s rules, even where the numeric results happen to match? A) It doesn’t differ from either — all three use the same underlying rule B) It rounds toward positive infinity — a distinct rule from Excel’s “away from zero” and Python’s “to even,” even on inputs where it happens to land on the same number as one of them C) It always throws an error on negative numbers D) Only positive numbers are supported Answer: B.
Concept: Cross-platform divergence
Q9. Given input 2.5, which platforms from Example 3 agree with each other and differ from JavaScript’s positive-side result? A) None — all five platforms agree on 2.5 B) Python and R both round to 2, while Excel, MATLAB, and JavaScript all round to 3 C) Only MATLAB differs D) Only Excel differs Answer: B.
Q10. Why does this cross-platform divergence matter practically? A) It never matters — differences are always negligible B) A calculation rebuilt in a different tool can produce a different final digit at a tie, with no error in either tool’s logic C) Only academic exercises are affected D) Only currency calculations are ever affected Answer: B.
Same Tie, Three Rules
Input: -2.5
- → -3: Excel, Google Sheets, MATLAB (half away from zero)
- → -2: Python, R (half to even) and JavaScript (half toward positive infinity) — same result, different rule
Quick Reference
| Task | Tool | How |
|---|---|---|
| Round to N sig figs | Excel / Sheets | =ROUND(x, N-1-INT(LOG10(ABS(x)))) |
| Round to N sig figs | R | signif(x, N) — no formula needed |
| Round to N sig figs | Python | Small helper function around round(), or use decimal |
| Avoid floating-point error | Python | decimal module |
| Avoid floating-point error | This site’s tools | Arbitrary-precision decimal engine (see the SignificantFiguresCalculator rule) |
| Round to N sig figs | MATLAB | round(x, N, 'significant') — native support |
Continue Learning
Related fundamentals:
Go deeper on one platform at a time:
- How to Round to Significant Figures in Excel
- Significant Figures in Google Sheets
- Rounding to Significant Figures in Python
- Why Python’s round() Uses Banker’s Rounding
- Floating Point Errors That Break Sig Fig Calculations
- Sig Figs in R, MATLAB, JavaScript, and SQL — Behavior Compared
- Scientific Notation on the TI-84 and Casio fx-991
Tools:
Sources and Further Reading
- MDN Web Docs, Math.round() — JavaScript — the primary source for JavaScript’s toward-positive-infinity tie-breaking behavior, including MDN’s own note distinguishing it from most other languages. (developer.mozilla.org)
- R Core Team, R: Rounding of Numbers (official R documentation) — the source for R’s IEC 60559 rounding behavior and its own documented caveat about representation error affecting values like 0.15, cited in Example 4. (stat.ethz.ch)
- note.nkmk.me, Round Numbers in Python — reused from our rounding pillar, confirming Python’s
round()implements round-half-to-even by default. (note.nkmk.me)
Review and Methodology
Reviewed by: [Pending — reviewer assignment required before publication] Last reviewed: [Pending] Methodology: Every platform-specific behavior claim is sourced to that platform’s own official documentation (MDN for JavaScript, R Core Team for R) rather than a secondary summary, and every formula and worked example was independently tested during drafting. This site’s own calculators use an arbitrary-precision decimal engine, not native floating-point math, validated against a versioned regression fixture set.
Changelog
v1.0 — Initial draft completed, 2026-08-10.
FAQ
Why does Python's round(2.5) return 2 instead of 3?
Python uses banker's rounding (round-half-to-even) as per IEEE 754 to minimize cumulative rounding errors in statistical operations. To get half-up rounding, use the decimal module with ROUND_HALF_UP.
How do I round to a specific number of significant figures in Excel?
Use the formula: =ROUND(number, sigfigs - 1 - INT(LOG10(ABS(number)))). For example, to round 1234 to 3 significant figures, use =ROUND(1234, 3-1-INT(LOG10(ABS(1234)))) which returns 1230.
Does Google Sheets handle significant figures differently from Excel?
No, both use the same ROUND function and half-up rounding. The custom formula for significant figures works identically in both.
Leave a Reply