Python provides multiple mechanisms to round numbers, led by the built-in round(number, ndigits=None) function. Python implements the IEEE 754 standard Banker's Rounding (Round-Half-to-Even): when a number is halfway between two possibilities (e.g. 2.5 or 3.5), it rounds to the nearest even number (round(2.5) == 2 and round(3.5) == 4) to eliminate cumulative statistical bias.
Return Type Nuance: Calling round(x) with ndigits=None returns an int. Passing ndigits ≥ 0 returns a float, while negative ndigits rounds to tens, hundreds, or thousands.
The round() function is a core Python built-in and requires no module imports:
rounded_value = round(number, ndigits=None)
| Parameter | Type | Description |
|---|---|---|
number |
float or int |
Required. The numeric value to be rounded. |
ndigits |
int or None |
Optional (default=None). Number of decimal places. Positive rounds decimals; zero rounds to nearest whole float; negative rounds to powers of 10. |
| Return Value | int or float |
Returns an int if ndigits=None; returns a float if ndigits is an integer (or preserves input type for custom classes). |
TypeError |
Exception | Raised when number is non-numeric or ndigits is not an integer. |
Passing different values for ndigits controls whether you round to decimals, whole numbers, or orders of magnitude:
# 1. Omitting ndigits returns an int
print("round(12.34): ", round(12.34), type(round(12.34))) # 12 <class 'int'>
print("round(12.89): ", round(12.89), type(round(12.89))) # 13 <class 'int'>
# 2. Positive ndigits returns a float rounded to decimal places
print("round(12.34567, 2):", round(12.34567, 2)) # 12.35 <class 'float'>
print("round(12.34567, 4):", round(12.34567, 4)) # 12.3457
# 3. Negative ndigits rounds to tens, hundreds, and thousands
print("round(1245, -1): ", round(1245, -1)) # Nearest 10: 1250
print("round(1245, -2): ", round(1245, -2)) # Nearest 100: 1200
print("round(1745, -3): ", round(1745, -3)) # Nearest 1000: 2000
Output:
round(12.34): 12 <class 'int'>
round(12.89): 13 <class 'int'>
round(12.34567, 2): 12.35
round(12.34567, 4): 12.3457
round(1245, -1): 1250
round(1245, -2): 1200
round(1745, -3): 2000
Most schools teach "round half up" (where any fraction ≥ 0.5 rounds upwards). However, Python follows the IEEE 754 standard known as Banker's Rounding (Round-Half-to-Even):
# Halfway numbers round to the nearest EVEN integer:
print("round(0.5):", round(0.5)) # 0 is even -> 0
print("round(1.5):", round(1.5)) # 2 is even -> 2
print("round(2.5):", round(2.5)) # 2 is even -> 2
print("round(3.5):", round(3.5)) # 4 is even -> 4
print("round(4.5):", round(4.5)) # 4 is even -> 4
print("round(5.5):", round(5.5)) # 6 is even -> 6
Output:
round(0.5): 0
round(1.5): 2
round(2.5): 2
round(3.5): 4
round(4.5): 4
round(5.5): 6
0.5 upwards, summing thousands of rounded numbers introduces a systematic positive drift (+0.5 bias on average per halfway number). By rounding half towards even, half of the ties round up and half round down, maintaining an unbiased expected mean.
A classic complaint among Python developers is why round(2.675, 2) yields 2.67 instead of 2.68. This is not a bug in Python; it is an inherent artifact of binary floating-point representation:
print("round(2.675, 2):", round(2.675, 2)) # Output: 2.67
# Inspect the exact underlying 53-bit IEEE 754 binary representation:
print(f"Exact representation: {2.675:.25f}")
Output:
round(2.675, 2): 2.67
Exact representation: 2.6749999999999998223643161
Because 2.675 is stored internally as 2.6749999999999998..., the number is strictly less than halfway to 2.68. Consequently, Python correctly rounds down to 2.67.
For financial accounting and invoicing where statutory regulations require exact decimal arithmetic, use Python's standard decimal module:
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
# Pass strings to Decimal to avoid float binary conversion artifacts
val = Decimal('2.675')
# 1. Traditional School Rounding (Round Half Up)
half_up = val.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
print("ROUND_HALF_UP (School): ", half_up) # Output: 2.68
# 2. Exact Banker's Rounding (Round Half Even)
half_even = val.quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)
print("ROUND_HALF_EVEN (Banker):", half_even) # Output: 2.68
Output:
ROUND_HALF_UP (School): 2.68
ROUND_HALF_EVEN (Banker): 2.68
Review how each rounding function behaves across positive, negative, and halfway inputs:
| Input | round(x) |
math.floor(x) |
math.ceil(x) |
math.trunc(x) |
|---|---|---|---|---|
2.2 |
2 |
2 |
3 |
2 |
2.5 |
2 (even) |
2 |
3 |
2 |
2.8 |
3 |
2 |
3 |
2 |
3.5 |
4 (even) |
3 |
4 |
3 |
−2.5 |
−2 (even) |
−3 |
−2 |
−2 |
−2.8 |
−3 |
−3 |
−2 |
−2 |
In retail and commerce, systems must handle two different rounding requirements:
0.05).import math
from decimal import Decimal, ROUND_HALF_UP
def calculate_sales_tax(subtotal_dollars, tax_rate_percent):
"""
Computes exact sales tax with traditional ROUND_HALF_UP rounding.
"""
if subtotal_dollars < 0 or tax_rate_percent < 0:
raise ValueError("Subtotal and tax rate must be non-negative.")
sub_dec = Decimal(str(subtotal_dollars))
rate_dec = Decimal(str(tax_rate_percent)) / Decimal('100')
raw_tax = sub_dec * rate_dec
tax_cents = raw_tax.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
return float(tax_cents)
def swedish_cash_round(amount, step=0.05):
"""
Rounds a monetary total to the nearest cash denomination (e.g. 0.05).
"""
if amount < 0 or step <= 0:
raise ValueError("Amount and step must be positive.")
# Scale by 1/step, round, then scale back
units = round(amount / step)
return round(units * step, 2)
# Unit Assertions
# 1. Tax on $35.45 at 8.25%: 35.45 * 0.0825 = 2.924625 -> $2.92
assert calculate_sales_tax(35.45, 8.25) == 2.92
# 2. Tax on $49.99 at 7.5%: 49.99 * 0.075 = 3.74925 -> $3.75
assert calculate_sales_tax(49.99, 7.5) == 3.75
# 3. Cash rounding checks to nearest 5 cents
assert swedish_cash_round(10.02) == 10.00
assert swedish_cash_round(10.03) == 10.05
assert swedish_cash_round(10.07) == 10.05
assert swedish_cash_round(10.08) == 10.10
print("Sales tax on $100 at 8.875%:", calculate_sales_tax(100.0, 8.875))
print("Cash total for $15.43: ", swedish_cash_round(15.43))
print("All sales tax & POS rounding assertions passed successfully!")
Open in Google Colab View on GitHub
Run all rounding examples interactively, test banker's round-half-to-even behavior, explore the Decimal module, and execute cash register denomination rounding in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.