How to format numbers in Python

Learn how to format numbers in Python. This guide covers different methods, tips, real-world applications, and how to debug common errors.

How to format numbers in Python
Published on: 
Wed
Mar 25, 2026
Updated on: 
Thu
Mar 26, 2026
The Replit Team

Proper number format in Python is essential for clear data presentation. You can control decimal places, add currency symbols, and align outputs. Python offers powerful tools to make numbers readable and professional.

In this article, you'll explore techniques from f-strings to the format() method. You'll also find practical tips, see real-world applications, and get advice to debug common format issues effectively.

Using the str.format() method for basic number formatting

number = 1234.56789
formatted = "The number is {:.2f}".format(number)
print(formatted)--OUTPUT--The number is 1234.57

The str.format() method offers a powerful way to control how numbers appear in your strings. It uses a mini-language within the string to define the output format. The magic happens inside the curly braces, which act as placeholders that get replaced by the arguments passed to format().

The specifier {:.2f} breaks down like this:

  • The : starts the format spec.
  • .2 sets the precision to two decimal places, triggering rounding.
  • f formats the number as a fixed-point number.

This combination instructs Python to round the original number and display it with a clean, two-digit decimal finish, turning 1234.56789 into 1234.57.

Basic number formatting techniques

Building on the str.format() method, you can also use f-strings or the older % operator to gain even finer control over number presentation.

Using f-strings for number formatting

amount = 1234.56789
formatted = f"The price is ${amount:.2f}"
print(formatted)
print(f"With thousands separator: ${amount:,.2f}")--OUTPUT--The price is $1234.57
With thousands separator: $1,234.57

F-strings offer a modern and concise way to format numbers. By prefixing a string with an f, you can embed variables directly within curly braces. The format specifiers, like :.2f, function just as they do in the str.format() method.

  • A key advantage is adding a thousands separator. Simply place a comma before the precision specifier, as in f'{amount:,.2f}', to format the number with both a comma and two decimal places for better readability.

Controlling width and alignment with format()

number = 42.5
right_aligned = "|{:10.2f}|".format(number)
left_aligned = "|{:<10.2f}|".format(number)
center_aligned = "|{:^10.2f}|".format(number)
print(right_aligned, left_aligned, center_aligned, sep="\n")--OUTPUT--| 42.50|
|42.50 |
| 42.50 |

Beyond just setting decimal places, you can also control the total width and alignment of your numbers. The number before the dot in a format specifier—like the 10 in {:10.2f}—sets the total character width for the output. Python pads the extra space with whitespace to meet this width.

  • < left-aligns the number.
  • > right-aligns it, which is the default behavior if no symbol is used.
  • ^ centers the number perfectly within the defined space.

Using the % operator for number formatting

pi = 3.14159
percentage = 0.8543
print("Value of pi = %.3f" % pi)
print("Score: %.2f%%" % (percentage * 100))--OUTPUT--Value of pi = 3.142
Score: 85.43%

While newer methods exist, the % operator offers a classic, C-style approach to string formatting. You place format specifiers like %.3f in your string as placeholders, then follow the string with % and the variable you want to insert. It’s a straightforward substitution mechanism.

  • The specifier %.3f formats the number as a floating-point value (f) rounded to three decimal places.
  • If you need to print a literal percent sign, you have to escape it by typing %%. A single % is always treated as the start of a format specifier.

Advanced number formatting approaches

Once you're comfortable with basic formatting, you can tackle more complex scenarios like displaying scientific notation, converting number bases, and localizing formats for international audiences.

Formatting different number bases

number = 255
print(f"Decimal: {number}")
print(f"Binary: {number:b}")
print(f"Octal: {number:o}")
print(f"Hexadecimal: {number:x}")
print(f"Hexadecimal (uppercase): {number:X}")--OUTPUT--Decimal: 255
Binary: 11111111
Octal: 377
Hexadecimal: ff
Hexadecimal (uppercase): FF

Python makes it simple to represent integers in different number systems. Within an f-string, you just add a specific type code after the colon to handle the conversion. This is especially useful in low-level programming or data representation tasks.

The format specifiers are straightforward:

  • b converts the number to its binary form.
  • o provides the octal representation.
  • x and X produce lowercase and uppercase hexadecimal output, respectively.

Using scientific and engineering notation

number = 12345.6789
scientific = f"{number:e}"
engineering = f"{number:.2e}"
print(f"Scientific notation: {scientific}")
print(f"Engineering notation (2 decimals): {engineering}")--OUTPUT--Scientific notation: 1.234568e+04
Engineering notation (2 decimals): 1.23e+04

For very large or small numbers, scientific notation offers a more readable format. With f-strings, it's simple to switch to this style using the e type code in your format specifier.

  • The e specifier converts a number into scientific notation, representing it with a coefficient and an exponent. For instance, 12345.6789 becomes 1.234568e+04.
  • You can also control the precision. Adding a decimal point, like in .2e, rounds the number to two decimal places for a cleaner output like 1.23e+04.

Working with the locale module for regional formatting

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
number = 1234567.89
formatted = locale.format_string("%.2f", number, grouping=True)
currency = locale.currency(number)
print(formatted)
print(currency)--OUTPUT--1,234,567.89
$1,234,567.89

When you need to format numbers for a specific region, Python's locale module is your go-to tool. It adapts formatting conventions—like currency symbols and thousand separators—based on location. You start by setting the desired region with locale.setlocale(locale.LC_ALL, 'en_US.UTF-8'), which configures the session for US English formatting.

  • The locale.format_string() function applies these rules. Using grouping=True automatically adds the correct thousands separators.
  • For money values, locale.currency() is a convenient shortcut that formats the number with the appropriate local currency symbol.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. You can describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

The number formatting techniques in this article can be the foundation for powerful tools. Replit Agent can turn these concepts into production-ready applications:

  • A loan calculator that uses the locale module to display payments with regional currency symbols and correct decimal precision.
  • A scientific data visualizer that formats large values with scientific notation and neatly aligns them in columns for easy comparison.
  • A developer utility that converts numbers between decimal, binary, octal, and hexadecimal representations on the fly.

Instead of just formatting numbers, you can build the entire application around them. Describe your app idea and let Replit Agent write the code, handle testing, and deploy it for you, all from your browser.

Common errors and challenges

Even with powerful tools, you can run into formatting errors; here’s how to navigate the most common ones.

  • Fixing missing colons in format() specifiers: A frequent mistake is forgetting the colon in a format specifier. Writing something like "{.2f}".format(num) will raise a ValueError because Python expects a : to separate the field name from the format instructions. Always ensure your specifier starts correctly, as in "{:.2f}".
  • Handling division by zero in formatted calculations: Formatting can't fix impossible math. If your code attempts to divide by zero, Python will raise a ZeroDivisionError before the formatting function even runs. You can prevent your program from crashing by wrapping the calculation in a try-except block to catch the error and handle it gracefully.
  • Resolving type errors with numeric format() specifiers: Applying a numeric format specifier to a non-numeric type is a classic pitfall. For example, using "{:.2f}".format("123") triggers a ValueError because the f specifier requires a number, not a string. Before formatting, confirm your variable is an int or float, or convert it if necessary.

Fixing missing colons in format() specifiers

It’s easy to miss the colon inside a format specifier, but Python won't let it slide. Forgetting it triggers a ValueError because the interpreter can't parse the instruction. Take a look at the following code, which makes this exact mistake.

amount = 49.95
quantity = 3
total = "Total: ${0.2f} for {1} items".format(amount, quantity)
print(total)

The format string {0.2f} is invalid because it lacks a colon. Python reads 0.2f as a field name instead of a format spec, causing a ValueError. See how a small change fixes the code below.

amount = 49.95
quantity = 3
total = "Total: ${0:.2f} for {1} items".format(amount, quantity)
print(total)

The corrected code works because adding a colon in {0:.2f} properly separates the argument's position (0) from its format specifier (.2f). Without the colon, Python misinterprets 0.2f as a field name, which isn't valid, and raises a ValueError. It's a common slip-up, especially when formatting multiple values at once. Always double-check your curly braces to ensure the colon is present before any formatting instructions.

Handling division by zero in formatted calculations

Even the slickest formatting can't save a calculation from breaking mathematical rules. If your code tries to divide by zero, Python halts everything and raises a ZeroDivisionError before any formatting occurs. See what happens in the code below.

def calculate_percentage(part, total):
percentage = part / total
return "Percentage: {:.2%}".format(percentage)

print(calculate_percentage(25, 0))

The calculate_percentage function is called with a total of 0, making the division part / total impossible. This triggers the error before the string can be formatted. The corrected code below shows how to handle this gracefully.

def calculate_percentage(part, total):
if total == 0:
return "Percentage: N/A (division by zero)"
percentage = part / total
return "Percentage: {:.2%}".format(percentage)

print(calculate_percentage(25, 0))

The fix is to add a simple check, if total == 0:, before the calculation. This guard clause intercepts the zero and returns a user-friendly message instead of attempting the impossible division. You should always anticipate this issue when a denominator could be zero, particularly with user input or external data. This proactive check keeps your application from crashing and provides a much better user experience than a raw error message.

Resolving type errors with numeric format() specifiers

Applying a numeric format specifier to a non-numeric type is a classic pitfall. Python expects a number for operations like :.2f, so using it on a string—even one with digits—causes a ValueError. The following code demonstrates this common error.

price = "45.99"
discount = 0.15
result = f"Discounted price: ${price:.2f}"
print(result)

The :.2f format specifier is meant for numbers, but the price variable holds a string. This type mismatch is what causes the ValueError. See how the corrected code below addresses this before formatting.

price = "45.99"
discount = 0.15
discounted = float(price) * (1 - discount)
result = f"Discounted price: ${discounted:.2f}"
print(result)

The fix is to explicitly convert the price string to a number with float() before doing any math. This new float value, stored in the discounted variable, can then be formatted correctly with :.2f. You should always be mindful of this when working with data from user input or APIs, as it often arrives as a string even when it looks like a number.

Real-world applications

Now that you can troubleshoot common issues, you can apply these formatting techniques to create professional invoices and clear data analysis reports.

Creating an invoice with f-strings and alignment

You can combine f-strings with alignment specifiers to generate a neatly formatted invoice, ensuring all your columns for items, quantities, and prices line up perfectly.

items = [("Widget A", 2, 19.99), ("Widget B", 3, 14.95)]
subtotal = sum(quantity * price for _, quantity, price in items)
tax = subtotal * 0.08
total = subtotal + tax

for name, qty, price in items:
print(f"{name:<10} {qty:>3} ${price:>7.2f} ${qty*price:>9.2f}")
print(f"{'Subtotal':>24} ${subtotal:>9.2f}")
print(f"{'Total':>24} ${total:>9.2f}")

This snippet first calculates the subtotal, tax, and total from a list of items. The core of the logic lies in the print statements, which use f-string formatting to build a structured layout without needing a table.

  • The < and > symbols control text alignment within a specified width. For example, {name:<10} left-aligns the item name within a 10-character space.
  • In contrast, {qty:>3} right-aligns the quantity, which is ideal for lining up numbers. This technique is used for all values to create a clean, organized output.

Formatting data analysis results with multiple format specifiers

When presenting data analysis results, you can use a mix of format specifiers to ensure each value—from temperatures to percentages—is displayed in its most readable form.

temperatures = [32.5, 30.7, 29.8, 31.2, 33.1]
stock_changes = [-0.025, 0.048, -0.015, 0.073]
power_usage = [3215478, 3456291, 3891042]

avg_temp = sum(temperatures) / len(temperatures)
avg_stock = sum(stock_changes) / len(stock_changes)
total_power = sum(power_usage)

print(f"Temperature: {avg_temp:.1f}°C")
print(f"Stock change: {avg_stock:.2%}")
print(f"Power used: {total_power:,.0f} kWh")

This snippet calculates summary statistics from three lists and uses f-strings to present each result uniquely. After computing averages with sum() and len(), it applies specific format codes to tailor the output.

  • The temperature is rounded to one decimal with :.1f.
  • The stock change is converted to a percentage using :.2%.
  • The power usage gets a thousands separator for clarity with :,.0f.

This shows how you can apply different formatting rules within the same block of code to match the context of each data point.

Get started with Replit

Turn your new formatting skills into a real tool. Tell Replit Agent to "build a loan calculator with region-specific currency formatting" or "create a utility that converts numbers to scientific notation".

Replit Agent writes the code, tests for errors, and deploys your app. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.