How to Round Numbers to 2 Decimal Places in Python

To round a number to 2 decimal places in Python, use round(value, 2): round(1234.5678, 2) returns 1234.57. If you only need the number to look right on screen, format it instead with an f-string: f"{value:.2f}", or f"${value:,.2f}" for dollars. For money, use the decimal module so half-cents always round up. This guide shows each way to round to two decimal places, when to use which, and the float surprises that make round(2.675, 2) return 2.67.

Every example was run with Python 3.12.5, NumPy 2.5.3 and pandas 3.0.6 in the Windows Command Prompt, and the output shown is the real output. Reference: round(), format specification and decimal in the Python docs.

Round to 2 decimal places in Python

price = 1234.5678

print(round(price, 2))        # a number, rounded
print(f"{price:.2f}")         # text, formatted for display
print(f"${price:,.2f}")       # US currency style

Output:

1234.57
1234.57
$1,234.57
Command Prompt output of Python rounding 1234.5678 to 2 decimal places with round(), an f-string and dollar formatting
round() returns a number; the f-string returns text ready to display.
GoalUseResult for 1234.5678
Round the value for more mathsround(x, 2)1234.57 (float)
Show 2 decimals on screenf"{x:.2f}"'1234.57' (string)
Show moneyf"${x:,.2f}"'$1,234.57'
Invoices and billingDecimal(str(x)).quantize(...)exact cents, half up

The round() function

round() takes the number and how many decimal places you want. Without the second argument it returns an int, and a negative number rounds to tens, hundreds and so on:

total = 1234.5678

print(round(total, 2))        # 2 decimal places
print(round(total, 1))        # 1 decimal place
print(round(total))           # no second argument -> an int
print(type(round(total)).__name__)
print(round(total, -2))       # negative digits round to hundreds

Output:

1234.57
1234.6
1235
int
1200.0

Format a number to 2 decimal places (f-string, format, %)

Formatting keeps the original value and produces text. It also pads with zeros, so 5 becomes 5.00, which round() never does:

amount = 98765.4321

print(f"{amount:.2f}")            # f-string (Python 3.6+)
print("{:.2f}".format(amount))    # str.format()
print("%.2f" % amount)            # old printf style
print(f"{amount:,.2f}")           # thousands separators
print(f"{amount:>12,.2f}")        # right aligned in 12 characters
print(f"{0.19876:.2%}")           # percentage with 2 decimals

Output:

98765.43
98765.43
98765.43
98,765.43
   98,765.43
19.88%

round() vs formatting: which one do you need?

Use round() when the number goes into further calculations, and formatting when the number is about to be printed, written to a report or shown in a template:

price = 19.567

rounded = round(price, 2)      # still a float
text = f"{price:.2f}"          # now a string

print(rounded, type(rounded).__name__)
print(text, type(text).__name__)
print(rounded * 2)             # maths works on the number
print(text * 2)                # but "*" repeats the string instead
print(float(text) * 2)         # convert back first

Output:

19.57 float
19.57 str
39.14
19.5719.57
39.14

Why round(2.675, 2) returns 2.67

This is the question behind most “Python rounding is broken” reports. Two different things are happening:

from decimal import Decimal

print(round(2.675, 2))                  # expected 2.68
print(Decimal(2.675))                   # why: 2.675 is not exactly 2.675 in binary

print([round(x) for x in (0.5, 1.5, 2.5, 3.5)])        # round half to even
print([round(x, 2) for x in (1.005, 2.665, 2.675, 0.125, 0.135)])

Output:

2.67
2.67499999999999982236431605997495353221893310546875
[0, 2, 2, 4]
[1.0, 2.67, 2.67, 0.12, 0.14]
Command Prompt output showing round(2.675, 2) returning 2.67, the exact binary value of 2.675 and Python round half to even behaviour
2.675 is stored as 2.67499999…, so it rounds down.
  • Binary floats: 2.675 cannot be stored exactly. Python keeps 2.674999999999999822…, which is below the halfway point, so it rounds down to 2.67.
  • Round half to even: when a value really is exactly halfway, Python rounds to the nearest even digit, so round(0.5) is 0 and round(2.5) is 2. This is the IEEE 754 default and it keeps large sums unbiased.
  • Both are correct behaviour, not bugs. When you need the school rule (0.005 always up), use Decimal, as shown next.

Round money to 2 decimals with Decimal

For invoices, taxes and prices, use decimal and pass the value as a string. A float is already imprecise before Decimal ever sees it:

from decimal import Decimal, ROUND_HALF_UP

invoice = Decimal("2.675")                              # pass a STRING, not a float
print(invoice.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))

print(Decimal(2.675).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))   # float input: still 2.67

def to_cents(value):
    """Round a price the way an invoice does: 0.005 always goes up."""
    return Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

for value in (2.675, 19.994, 5.005, 0.125):
    print(f"{value:<8} -> {to_cents(value)}")

Output:

2.68
2.67
2.675    -> 2.68
19.994   -> 19.99
5.005    -> 5.01
0.125    -> 0.13
Command Prompt output of Python Decimal quantize with ROUND_HALF_UP rounding 2.675 to 2.68 from a string and 2.67 from a float
From a string, 2.675 rounds up to 2.68 as an accountant expects.

More on exact numbers in converting floats to integers in Python.

Round up or down to 2 decimal places

round() goes to the nearest value. To force the direction, use math.ceil() and math.floor() with a factor of 100, or Decimal with an explicit rounding mode:

import math
from decimal import Decimal, ROUND_CEILING, ROUND_FLOOR

shipping = 12.341

print(math.ceil(shipping * 100) / 100)      # always up
print(math.floor(shipping * 100) / 100)     # always down (truncate)

print(Decimal("12.341").quantize(Decimal("0.01"), rounding=ROUND_CEILING))
print(Decimal("12.349").quantize(Decimal("0.01"), rounding=ROUND_FLOOR))
print(int(shipping * 100) / 100)            # int() also truncates

Output:

12.35
12.34
12.35
12.34
12.34

Round a NumPy array or pandas DataFrame

Both libraries round whole columns at once. Note that NumPy does the scaling differently, so np.round(2.675, 2) gives 2.68 where the built-in round() gives 2.67:

import numpy as np
import pandas as pd

prices = np.array([2.675, 19.994, 5.005, 12.3456])
print(np.round(prices, 2))                  # NumPy: note 2.675 -> 2.68
print(round(2.675, 2), "<- built-in round() gives 2.67")

df = pd.DataFrame({"price": [19.994, 5.005, 12.3456], "qty": [3, 2, 1]})
df["total"] = (df["price"] * df["qty"]).round(2)
print(df.round(2).to_string(index=False))
print(df["total"].map(lambda v: f"${v:,.2f}").tolist())     # display as money

Output:

[ 2.68 19.99  5.   12.35]
2.67 <- built-in round() gives 2.67
 price  qty  total
 19.99    3  59.98
  5.00    2  10.01
 12.35    1  12.35
['$59.98', '$10.01', '$12.35']
Command Prompt output of numpy round and pandas DataFrame round to 2 decimal places with a total column formatted as dollars
DataFrame.round(2) rounds every numeric column; formatting turns them into dollars.

Related: convert floats to integers in pandas and change the data type of a column.

Mistakes to avoid

values = [0.005, 0.005, 0.005, 0.005]

print(sum(values))                                  # 0.02
print(round(sum(values), 2))                        # round once at the end
print(sum(round(v, 2) for v in values))             # rounding first changes the total

try:
    round("3.14159", 2)                             # round() needs a number
except TypeError as e:
    print("TypeError:", e)
print(round(float("3.14159"), 2))

print(0.1 + 0.2, "->", round(0.1 + 0.2, 2))

Output:

0.02
0.02
0.04
TypeError: type str doesn't define __round__ method
3.14
0.30000000000000004 -> 0.3
  • Round once, at the end. In the example, four values of 0.005 add up to 0.02, but rounding each one first turns the total into 0.04 — rounding early changes the answer.
  • round() needs a number. round("3.14159", 2) raises TypeError; convert with float() first.
  • Do not store money as floats in accounting code. Use Decimal (or whole cents as integers) and format only when displaying.
  • Formatting does not change the value: f"{x:.2f}" is text, so convert it back with float() if you need to calculate with it.

More Python number tutorials:

Frequently asked questions

How do I round to 2 decimal places in Python?

Use round(value, 2). For display only, use an f-string: f"{value:.2f}".

Why does round(2.675, 2) give 2.67 instead of 2.68?

2.675 cannot be stored exactly in binary; Python holds 2.67499999999999982…, which rounds down. Use Decimal("2.675").quantize(Decimal("0.01"), rounding=ROUND_HALF_UP) to get 2.68.

What is the difference between round() and an f-string?

round() returns a number you can keep calculating with; the f-string returns a string for display and always shows two decimals, including trailing zeros.

How do I always round up to 2 decimals?

math.ceil(value * 100) / 100, or Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_CEILING).

How do I show 2 decimal places with a dollar sign and commas?

f"${value:,.2f}" gives $1,234.57.

How do I round a pandas column to 2 decimals?

df["price"] = df["price"].round(2), or df.round(2) for every numeric column.