I feel compelled to provide a counterpoint to Ashwini Chaudhary's answer. Despite appearances, the two-argument form of the round function does not round a Python float to a given number of decimal places, and it's often not the solution you want, even when you think it is. Let me explain...

The ability to round a (Python) float to some number of decimal places is something that's frequently requested, but turns out to be rarely what's actually needed. The beguilingly simple answer round(x, number_of_places) is something of an attractive nuisance: it looks as though it does what you want, but thanks to the fact that Python floats are stored internally in binary, it's doing something rather subtler. Consider the following example:

>>> round(52.15, 1)
52.1

With a naive understanding of what round does, this looks wrong: surely it should be rounding up to 52.2 rather than down to 52.1? To understand why such behaviours can't be relied upon, you need to appreciate that while this looks like a simple decimal-to-decimal operation, it's far from simple.

So here's what's really happening in the example above. (deep breath) We're displaying a decimal representation of the nearest binary floating-point number to the nearest n-digits-after-the-point decimal number to a binary floating-point approximation of a numeric literal written in decimal. So to get from the original numeric literal to the displayed output, the underlying machinery has made four separate conversions between binary and decimal formats, two in each direction. Breaking it down (and with the usual disclaimers about assuming IEEE 754 binary64 format, round-ties-to-even rounding, and IEEE 754 rules):

  1. First the numeric literal 52.15 gets parsed and converted to a Python float. The actual number stored is 7339460017730355 * 2**-47, or 52.14999999999999857891452847979962825775146484375.

  2. Internally as the first step of the round operation, Python computes the closest 1-digit-after-the-point decimal string to the stored number. Since that stored number is a touch under the original value of 52.15, we end up rounding down and getting a string 52.1. This explains why we're getting 52.1 as the final output instead of 52.2.

  3. Then in the second step of the round operation, Python turns that string back into a float, getting the closest binary floating-point number to 52.1, which is now 7332423143312589 * 2**-47, or 52.10000000000000142108547152020037174224853515625.

  4. Finally, as part of Python's read-eval-print loop (REPL), the floating-point value is displayed (in decimal). That involves converting the binary value back to a decimal string, getting 52.1 as the final output.

In Python 2.7 and later, we have the pleasant situation that the two conversions in step 3 and 4 cancel each other out. That's due to Python's choice of repr implementation, which produces the shortest decimal value guaranteed to round correctly to the actual float. One consequence of that choice is that if you start with any (not too large, not too small) decimal literal with 15 or fewer significant digits then the corresponding float will be displayed showing those exact same digits:

>>> x = 15.34509809234
>>> x
15.34509809234

Unfortunately, this furthers the illusion that Python is storing values in decimal. Not so in Python 2.6, though! Here's the original example executed in Python 2.6:

>>> round(52.15, 1)
52.200000000000003

Not only do we round in the opposite direction, getting 52.2 instead of 52.1, but the displayed value doesn't even print as 52.2! This behaviour has caused numerous reports to the Python bug tracker along the lines of "round is broken!". But it's not round that's broken, it's user expectations. (Okay, okay, round is a little bit broken in Python 2.6, in that it doesn't use correct rounding.)

Short version: if you're using two-argument round, and you're expecting predictable behaviour from a binary approximation to a decimal round of a binary approximation to a decimal halfway case, you're asking for trouble.

So enough with the "two-argument round is bad" argument. What should you be using instead? There are a few possibilities, depending on what you're trying to do.

  • If you're rounding for display purposes, then you don't want a float result at all; you want a string. In that case the answer is to use string formatting:

    >>> format(66.66666666666, '.4f')
    '66.6667'
    >>> format(1.29578293, '.6f')
    '1.295783'
    

    Even then, one has to be aware of the internal binary representation in order not to be surprised by the behaviour of apparent decimal halfway cases.

    >>> format(52.15, '.1f')
    '52.1'
    
  • If you're operating in a context where it matters which direction decimal halfway cases are rounded (for example, in some financial contexts), you might want to represent your numbers using the Decimal type. Doing a decimal round on the Decimal type makes a lot more sense than on a binary type (equally, rounding to a fixed number of binary places makes perfect sense on a binary type). Moreover, the decimal module gives you better control of the rounding mode. In Python 3, round does the job directly. In Python 2, you need the quantize method.

    >>> Decimal('66.66666666666').quantize(Decimal('1e-4'))
    Decimal('66.6667')
    >>> Decimal('1.29578293').quantize(Decimal('1e-6'))
    Decimal('1.295783')
    
  • In rare cases, the two-argument version of round really is what you want: perhaps you're binning floats into bins of size 0.01, and you don't particularly care which way border cases go. However, these cases are rare, and it's difficult to justify the existence of the two-argument version of the round builtin based on those cases alone.

Answer from Mark Dickinson on Stack Overflow
Top answer
1 of 6
205

I feel compelled to provide a counterpoint to Ashwini Chaudhary's answer. Despite appearances, the two-argument form of the round function does not round a Python float to a given number of decimal places, and it's often not the solution you want, even when you think it is. Let me explain...

The ability to round a (Python) float to some number of decimal places is something that's frequently requested, but turns out to be rarely what's actually needed. The beguilingly simple answer round(x, number_of_places) is something of an attractive nuisance: it looks as though it does what you want, but thanks to the fact that Python floats are stored internally in binary, it's doing something rather subtler. Consider the following example:

>>> round(52.15, 1)
52.1

With a naive understanding of what round does, this looks wrong: surely it should be rounding up to 52.2 rather than down to 52.1? To understand why such behaviours can't be relied upon, you need to appreciate that while this looks like a simple decimal-to-decimal operation, it's far from simple.

So here's what's really happening in the example above. (deep breath) We're displaying a decimal representation of the nearest binary floating-point number to the nearest n-digits-after-the-point decimal number to a binary floating-point approximation of a numeric literal written in decimal. So to get from the original numeric literal to the displayed output, the underlying machinery has made four separate conversions between binary and decimal formats, two in each direction. Breaking it down (and with the usual disclaimers about assuming IEEE 754 binary64 format, round-ties-to-even rounding, and IEEE 754 rules):

  1. First the numeric literal 52.15 gets parsed and converted to a Python float. The actual number stored is 7339460017730355 * 2**-47, or 52.14999999999999857891452847979962825775146484375.

  2. Internally as the first step of the round operation, Python computes the closest 1-digit-after-the-point decimal string to the stored number. Since that stored number is a touch under the original value of 52.15, we end up rounding down and getting a string 52.1. This explains why we're getting 52.1 as the final output instead of 52.2.

  3. Then in the second step of the round operation, Python turns that string back into a float, getting the closest binary floating-point number to 52.1, which is now 7332423143312589 * 2**-47, or 52.10000000000000142108547152020037174224853515625.

  4. Finally, as part of Python's read-eval-print loop (REPL), the floating-point value is displayed (in decimal). That involves converting the binary value back to a decimal string, getting 52.1 as the final output.

In Python 2.7 and later, we have the pleasant situation that the two conversions in step 3 and 4 cancel each other out. That's due to Python's choice of repr implementation, which produces the shortest decimal value guaranteed to round correctly to the actual float. One consequence of that choice is that if you start with any (not too large, not too small) decimal literal with 15 or fewer significant digits then the corresponding float will be displayed showing those exact same digits:

>>> x = 15.34509809234
>>> x
15.34509809234

Unfortunately, this furthers the illusion that Python is storing values in decimal. Not so in Python 2.6, though! Here's the original example executed in Python 2.6:

>>> round(52.15, 1)
52.200000000000003

Not only do we round in the opposite direction, getting 52.2 instead of 52.1, but the displayed value doesn't even print as 52.2! This behaviour has caused numerous reports to the Python bug tracker along the lines of "round is broken!". But it's not round that's broken, it's user expectations. (Okay, okay, round is a little bit broken in Python 2.6, in that it doesn't use correct rounding.)

Short version: if you're using two-argument round, and you're expecting predictable behaviour from a binary approximation to a decimal round of a binary approximation to a decimal halfway case, you're asking for trouble.

So enough with the "two-argument round is bad" argument. What should you be using instead? There are a few possibilities, depending on what you're trying to do.

  • If you're rounding for display purposes, then you don't want a float result at all; you want a string. In that case the answer is to use string formatting:

    >>> format(66.66666666666, '.4f')
    '66.6667'
    >>> format(1.29578293, '.6f')
    '1.295783'
    

    Even then, one has to be aware of the internal binary representation in order not to be surprised by the behaviour of apparent decimal halfway cases.

    >>> format(52.15, '.1f')
    '52.1'
    
  • If you're operating in a context where it matters which direction decimal halfway cases are rounded (for example, in some financial contexts), you might want to represent your numbers using the Decimal type. Doing a decimal round on the Decimal type makes a lot more sense than on a binary type (equally, rounding to a fixed number of binary places makes perfect sense on a binary type). Moreover, the decimal module gives you better control of the rounding mode. In Python 3, round does the job directly. In Python 2, you need the quantize method.

    >>> Decimal('66.66666666666').quantize(Decimal('1e-4'))
    Decimal('66.6667')
    >>> Decimal('1.29578293').quantize(Decimal('1e-6'))
    Decimal('1.295783')
    
  • In rare cases, the two-argument version of round really is what you want: perhaps you're binning floats into bins of size 0.01, and you don't particularly care which way border cases go. However, these cases are rare, and it's difficult to justify the existence of the two-argument version of the round builtin based on those cases alone.

2 of 6
115

Use the built-in function round():

In [23]: round(66.66666666666,4)
Out[23]: 66.6667

In [24]: round(1.29578293,6)
Out[24]: 1.295783

help on round():

round(number[, ndigits]) -> floating point number

Round a number to a given precision in decimal digits (default 0 digits). This always returns a floating point number. Precision may be negative.

🌐
W3Schools
w3schools.com › python › ref_func_round.asp
Python round() Function
Python Examples Python Compiler ... Python Training ... The round() function returns a floating point number that is a rounded version of the specified number, with the specified number of decimals....
Discussions

python - How to round a floating point number up to a certain decimal place? - Stack Overflow
Suppose I have 8.8333333333333339, and I want to convert it to 8.84. How can I accomplish this in Python? round(8.8333333333333339, 2) gives 8.83 and not 8.84. I am new to Python or programming in More on stackoverflow.com
🌐 stackoverflow.com
how to limit or round a float to only two decimals without rounding up
You can try the solution here: https://stackoverflow.com/a/62435913 More on reddit.com
🌐 r/learnpython
12
5
January 25, 2024
Rounding and float point precision
I think the key is 'after summing up the corresponding products for that row'. 195.5 does have an exact representation and if you do: x = 195.5 Then x is exactly 195.5 and will always round to 196. But if x is a sum of other floats then it's not necessarily 195.5 even if it rounds to 195.5 and displays as such. For example from my testing: y = 75.27+1/3 x = 120.23+y-1/3 print(repr(x)) => 195.49999999999997 Which rounds down. This is due to the floating point precision not being 100%, which causes the sum to be slightly off. repr will show you the full precision btw so feel free to use that to check. For your purposes it's probably worth rounding to 2dp or something first before rounding to the nearest int. More on reddit.com
🌐 r/learnpython
16
4
June 12, 2025
python - Simple way to round floats when printing - Stack Overflow
I am working on a project where it has to take user inputs and do calculations. What I am aiming for is the print to appear as Inform the customer they saved 0.71 today Not Inform the custome... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Server Academy
serveracademy.com › blog › python-round-function-tutorial
Python Round() Function Tutorial - Server Academy
The round() function in Python rounds a floating-point number to the nearest integer or specified number of decimal places.
🌐
Python documentation
docs.python.org › 3 › library › functions.html
Built-in Functions — Python 3.14.3 documentation
2 weeks ago - The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
🌐
NumPy
numpy.org › doc › 2.1 › reference › generated › numpy.round.html
numpy.round — NumPy v2.1 Manual
For positive decimals it is equivalent to np.true_divide(np.rint(a * 10**decimals), 10**decimals), which has error due to the inexact representation of decimal fractions in the IEEE floating point standard [1] and errors introduced when scaling by powers of ten. For instance, note the extra “1” in the following: >>> np.round(56294995342131.5, 3) 56294995342131.51
Top answer
1 of 12
111

8.833333333339 (or 8.833333333333334, the result of 106.00/12) properly rounded to two decimal places is 8.83. Mathematically it sounds like what you want is a ceiling function. The one in Python's math module is named ceil:

import math

v = 8.8333333333333339
print(math.ceil(v*100)/100)  # -> 8.84

Respectively, the floor and ceiling functions generally map a real number to the largest previous or smallest following integer which has zero decimal places — so to use them for 2 decimal places the number is first multiplied by 102 (or 100) to shift the decimal point and is then divided by it afterwards to compensate.

If you don't want to use the math module for some reason, you can use this (minimally tested) implementation I just wrote:

def ceiling(x):
    n = int(x)
    return n if n-1 < x <= n else n+1

How all this relates to the linked Loan and payment calculator problem:

From the sample output it appears that they rounded up the monthly payment, which is what many call the effect of the ceiling function. This means that each month a little more than 1⁄12 of the total amount is being paid. That made the final payment a little smaller than usual — leaving a remaining unpaid balance of only 8.76.

It would have been equally valid to use normal rounding producing a monthly payment of 8.83 and a slightly higher final payment of 8.87. However, in the real world people generally don't like to have their payments go up, so rounding up each payment is the common practice — it also returns the money to the lender more quickly.

2 of 12
72

This is normal (and has nothing to do with Python) because 8.83 cannot be represented exactly as a binary float, just as 1/3 cannot be represented exactly in decimal (0.333333... ad infinitum).

If you want to ensure absolute precision, you need the decimal module:

>>> import decimal
>>> a = decimal.Decimal("8.833333333339")
>>> print(round(a,2))
8.83
Find elsewhere
🌐
NumPy
numpy.org › doc › 2.2 › reference › generated › numpy.round.html
numpy.round — NumPy v2.2 Manual
For positive decimals it is equivalent to np.true_divide(np.rint(a * 10**decimals), 10**decimals), which has error due to the inexact representation of decimal fractions in the IEEE floating point standard [1] and errors introduced when scaling by powers of ten. For instance, note the extra “1” in the following: >>> np.round(56294995342131.5, 3) 56294995342131.51
🌐
Tutorialspoint
tutorialspoint.com › python › number_round.htm
Python round() Function
The Python round() function is used to round the given floating point number to the nearest integer value. The round is done with the specified number of decimal points. If the number of decimal places to round is not specified, it will round to the
🌐
Reddit
reddit.com › r/learnpython › rounding and float point precision
r/learnpython on Reddit: Rounding and float point precision
June 12, 2025 -

Hello all

Not an expert coder, but I can usually pick things up in Python. However, I found something that stumped me and hoping I can get some help.

I have a pandas data frame. In that df, I have several columns of floats. For each column, each entry is a product of given values, those given values extend to the hundredths place. Once the product is calculated, I round the product to two decimal places.

Finally, for each row, I sum up the values in each column to get a total. That total is rounded to the nearest integer. For the purpose of this project, the rounding rules I want to follow are “round-to-even.”

My understanding is that the round() function in Python defaults to the “round-to-even” rule, which is exactly what I need.

However, I saw that before rounding, one of my totals was 195.50 (after summing up the corresponding products for that row). So the round() function should have rounded this value to 196 according to “round-to-even” rules. But it actually output 195.

When I was doing some digging, I found that sometimes decimals have precision error because the decimal portion can’t be captured in binary notation. And that could be why the round() function inappropriately rounded to 195 instead of 196.

Now, I get the “big picture” of this, but I feel I am missing some critical details my understanding is that integers can always be repped as sums of powers of 2. But not all decimals can be. For example 0.1 is not the sum of powers of 2. In these situations, the decimal portion is basically approximated by a fraction and this approximation is what could lead to 0.1 really being 0.10000000000001 or something similar.

However, my understanding is that decimals that terminate with a 5 are possible to represent in binary. Thus the precision error shouldn’t apply and the round() function should appropriately round.

What am I missing? Any help is greatly appreciated

🌐
Python
docs.python.org › 3 › library › decimal.html
decimal — Decimal fixed-point and floating-point arithmetic
Source code: Lib/decimal.py The decimal module provides support for fast correctly rounded decimal floating-point arithmetic. It offers several advantages over the float datatype: Decimal “is based...
🌐
Real Python
realpython.com › python-rounding
How to Round Numbers in Python – Real Python
December 7, 2024 - Well, now you know how round_half_up(-1.225, 2) returns -1.23 even though there’s no logical error, but why does Python say that -1.225 * 100 is -122.50000000000001? Is there a bug in Python? Note*: For a hint about what’s happening, type the following in a Python interpreter session: ... Seeing this for the first time can be pretty shocking, but this is a classic example of the floating...
🌐
Mimo
mimo.org › glossary › python › round-function
Python round(): Rounding Numbers in Python
The Python round() function rounds floating-point numbers to a specified number of decimal places.
🌐
Python documentation
docs.python.org › 3 › tutorial › floatingpoint.html
15. Floating-Point Arithmetic: Issues and Limitations — Python 3.14.3 documentation
Instead of displaying the full decimal value, many languages (including older versions of Python), round the result to 17 significant digits: ... >>> from decimal import Decimal >>> from fractions import Fraction >>> Fraction.from_float(0.1) Fraction(3602879701896397, 36028797018963968) >>> (0.1).as_integer_ratio() (3602879701896397, 36028797018963968) >>> Decimal.from_float(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') >>> format(Decimal.from_float(0.1), '.17') '0.10000000000000001'
🌐
freeCodeCamp
freecodecamp.org › news › how-to-round-a-float-in-pandas
Pandas round() Method – How To Round a Float in Pandas
March 13, 2023 - Using the round() method, we rounded the values to 2 decimal places: df['cost'].round(2).
🌐
Note.nkmk.me
note.nkmk.me › home › python
Round Up/Down Decimals in Python: math.floor, math.ceil
January 15, 2024 - In Python, math.floor() and math.ceil() are used to round down and up floating point numbers (float). Contents · Round down (= take the floor): math.floor() Round up (= take the ceiling): math.ceil() Difference between math.floor() and int() ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › round-function-python
round() function in Python - GeeksforGeeks
Python round() function is a built-in function available with Python. It will return you a float number that will be rounded to the decimal places which are given as input. If the decimal places to be rounded are not specified, it is considered ...
Published   August 7, 2024
🌐
Inspector
inspector.dev › home › round up numbers to integer in python – fast tips
Round Up Numbers to Integer in Python - Inspector.dev
June 17, 2025 - The simplest way to round a number in Python is to use the built-in round() function. The round() function takes a number as the first argument and an optional second argument to specify the number of decimal places to round to.
🌐
Python.org
discuss.python.org › python help
How does round function handle scientific notation? - Python Help - Discussions on Python.org
December 5, 2022 - I’m currently working on a calculator program and am currently dealing with rounding. I want to round to 5 decimal places. Problem is, some functions in my program (for instance, tan(pi/2)) return scientific notation. I’m going to use tan(pi/2) as my example.