Explained clearly 6 min read

Why Python’s round() Uses Banker’s Rounding: A Precision Reference

Python's round() implements banker's rounding (round half to even) to reduce cumulative bias in statistical operations. This article explains the rationale, standards, and practical implications.

Short Answer

Python's round() implements banker's rounding (round half to even) to reduce cumulative bias in statistical operations. This article explains the rationale, standards, and practical implications.

When you call round(2.5) in Python, you might expect 3 based on the common “round half up” rule taught in many classrooms. Instead, Python returns 2. This behavior, known as banker’s rounding or round half to even, is not a quirk but a deliberate design choice rooted in statistical accuracy and international standards. This article, part of our precision and rounding reference, explains why Python adopts this convention, how it aligns with metrology standards, and what it means for your calculations.

Rule Statement

Banker’s rounding is a tie-breaking rule for rounding numbers exactly halfway between two possible rounded values. The rule states: when the fractional part is exactly 0.5, round to the nearest even digit. For example:

  • round(2.5)2 (2 is even)
  • round(3.5)4 (4 is even)
  • round(1.25, 1)1.2 (2 is even)
  • round(1.35, 1)1.4 (4 is even)

This rule applies to both positive and negative numbers. For negative numbers, the same logic applies to the absolute value: round(-2.5)-2 because 2 is even, and round(-3.5)-4 because 4 is even.

The rationale is to avoid the systematic upward bias introduced by the more common “round half up” rule. In a large dataset with many ties, half-up rounding consistently increases the average, whereas half-even rounding distributes ties evenly between even and odd results, keeping the statistical expectation unbiased.

Worked Examples

Let’s walk through several examples to see how banker’s rounding works in practice, including cases with a specified number of decimal places.

Example 1: Rounding to the Nearest Integer

  1. round(2.5) – The fractional part is exactly 0.5. The two nearest integers are 2 and 3. Since 2 is even, the result is 2.
  2. round(3.5) – The two nearest integers are 3 and 4. Since 4 is even, the result is 4.
  3. round(4.5) – The two nearest integers are 4 and 5. Since 4 is even, the result is 4.
  4. round(5.5) – The two nearest integers are 5 and 6. Since 6 is even, the result is 6.

Example 2: Rounding to a Specified Number of Decimal Places

When the second argument ndigits is provided, the same rule applies to the digit at that position.

  1. round(1.25, 1) – The digit in the tenths place is 2, and the next digit is 5 (exactly halfway). The two possible results are 1.2 and 1.3. Since 2 is even, the result is 1.2.
  2. round(1.35, 1) – The digit in the tenths place is 3, and the next digit is 5. The two possible results are 1.3 and 1.4. Since 4 is even, the result is 1.4.
  3. round(2.675, 2) – This is a classic pitfall. Due to binary floating-point representation, 2.675 is actually stored as 2.6749999999999998, so the result is 2.67, not 2.68. This is not a banker’s rounding issue but a floating-point precision artifact.

Counter-Examples

Understanding what banker’s rounding is not helps clarify its behavior. Here are common misconceptions and counter-examples:

  • Counter-example 1: round(2.5) does not return 3. Many expect half-up rounding, but Python returns 2.
  • Counter-example 2: round(1.25, 1) does not return 1.3. It returns 1.2 because 2 is even.
  • Counter-example 3: round(-2.5) does not return -3. It returns -2, following the same even-digit rule.
  • Counter-example 4: round(0.5) returns 0, not 1, because 0 is even.

These examples highlight that banker’s rounding is not symmetric in the way half-up is; it is symmetric in terms of bias reduction, not in terms of always rounding away from zero.

Convention Comparison Table

The table below compares the most common rounding methods for a set of tie values. The “tie” column indicates numbers exactly halfway between two rounding candidates.

Value Half-Up Half-Down Half-Even (Banker’s) Half-Odd
2.5 3 2 2 3
3.5 4 3 4 3
4.5 5 4 4 5
5.5 6 5 6 5
-2.5 -3 -2 -2 -3
-3.5 -4 -3 -4 -3

As seen, half-even rounding produces a mix of even and odd results, whereas half-up always rounds away from zero (for positive numbers) and half-down always rounds toward zero. The half-even method minimizes cumulative error in sums and averages.

Standards Citation

Banker’s rounding is not an arbitrary choice; it is endorsed by several international standards and metrology guidelines.

  • IEEE 754 (Standard for Floating-Point Arithmetic) specifies round-to-nearest-even as the default rounding mode for binary floating-point operations. Python’s round() for floats follows this standard.
  • ISO 80000-1:2009 (Quantities and units – Part 1: General) clause 7.3.4 recommends rounding to the nearest even digit when the discarded digit is exactly 5, to avoid systematic bias in statistical data.
  • NIST SP 811 (Guide for the Use of the International System of Units) section 7.2.2 discusses rounding rules and notes that “round half to even” is preferred for reducing rounding errors in calculations.
  • GUM (JCGM 100:2008) – Evaluation of measurement data – Guide to the expression of uncertainty in measurement, clause 7.2.6, advises using a rounding rule that does not introduce bias, implicitly supporting half-even.

These standards are used in scientific, engineering, and financial contexts to ensure that rounding does not distort results, especially when many numbers are rounded in a series.

Common Mistakes

Even experienced programmers and scientists can fall into traps when using round(). Here are the most frequent errors:

  • Assuming half-up rounding: Many expect round(2.5) to be 3. Always verify the tie-breaking rule in your language or tool.
  • Ignoring floating-point representation: Numbers like 2.675 are not stored exactly. The result of round(2.675, 2) is 2.67, not 2.68, due to binary approximation, not the rounding rule.
  • Using round() for financial calculations: For currency, use the decimal module with an explicit rounding mode (e.g., ROUND_HALF_UP) to match legal or accounting requirements.
  • Confusing round() with int() or floor(): int(2.5) truncates to 2, but round(2.5) also gives 2, which can mask the difference. For negative numbers, int(-2.5) gives -2, while round(-2.5) also gives -2, but for other values they diverge.
  • Not considering the second argument: round(2.5) and round(2.5, 0) are equivalent, but round(2.5, 1) would round to 2.5 (no tie).

Software Behavior Note

Python is not alone in using banker’s rounding. Many programming languages and tools adopt this convention for floating-point operations:

  • Python: round() uses round half to even for floats and for the decimal module when ROUND_HALF_EVEN is set (the default).
  • JavaScript: Math.round() uses half-up for positive numbers and half-down for negative numbers (i.e., it rounds toward +∞). This is different from Python.
  • Java: Math.round() uses half-up (rounds toward positive infinity for ties). However, BigDecimal allows explicit rounding modes.
  • C/C++: The round() function in the standard library uses half-away-from-zero, but rint() and nearbyint() use the current rounding mode, which defaults to round-to-nearest-even.
  • Excel: ROUND() uses half-up, while ROUNDHALFEVEN() is available in some versions.

This inconsistency across software is a common source of confusion. Always check the documentation for the specific language or tool you are using.

Quick Reference Table

Here is a quick reference for common round() calls in Python and their results:

Expression Result Explanation
round(2.5) 2 2 is even
round(3.5) 4 4 is even
round(4.5) 4 4 is even
round(5.5) 6 6 is even
round(1.25, 1) 1.2 2 is even
round(1.35, 1) 1.4 4 is even
round(-2.5) -2 2 is even
round(-3.5) -4 4 is even

Sources & Further Reading

For deeper understanding, consult the following authoritative resources:

  • Python Documentation: Built-in Functions – round()
  • IEEE 754-2019: Standard for Floating-Point Arithmetic
  • ISO 80000-1:2009: Quantities and units – Part 1: General
  • NIST SP 811: Guide for the Use of the International System of Units (SI)
  • JCGM 100:2008: Evaluation of measurement data – Guide to the expression of uncertainty in measurement (GUM)

These references provide the formal basis for rounding conventions and are essential for anyone working in metrology, data science, or scientific computing.

FAQ

Why does Python's round() use banker's rounding?

Python follows the IEEE 754 standard for floating-point arithmetic, which specifies round-to-nearest-even as the default rounding mode. This reduces cumulative bias in statistical calculations and is recommended by metrology standards like ISO 80000-1.

How can I get half-up rounding in Python?

For decimal numbers, use the decimal module with ROUND_HALF_UP. For floats, you can implement a custom function, but beware of floating-point representation issues. Example: def round_half_up(x, ndigits=0): import decimal; d = decimal.Decimal(x); return float(d.quantize(decimal.Decimal('1e-'+str(ndigits)), rounding=decimal.ROUND_HALF_UP)).

Does banker's rounding affect significant figures?

Yes. When rounding to a certain number of significant figures, the same tie-breaking rule applies. For instance, rounding 2.55 to two significant figures gives 2.6 (since 6 is even) under half-even, but 2.5 under half-up. This can lead to different results in scientific calculations.

Verified sources

References

  1. Python Software Foundation. Python 3 Documentation: Built-in Functions – round(). https://docs.python.org/3/library/functions.html#round
  2. IEEE 754-2019: IEEE Standard for Floating-Point Arithmetic. IEEE, 2019.
  3. ISO 80000-1:2009: Quantities and units – Part 1: General. International Organization for Standardization, 2009.
  4. NIST SP 811: Guide for the Use of the International System of Units (SI). National Institute of Standards and Technology, 2008.
  5. JCGM 100:2008: Evaluation of measurement data – Guide to the expression of uncertainty in measurement (GUM). Joint Committee for Guides in Metrology, 2008.

Leave a Reply

Your email address will not be published. Required fields are marked *