2314

I want a to be rounded to 13.95. I tried using round, but I get:

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

For the analogous issue with the standard library Decimal class, see How can I format a decimal to always show 2 decimal places?.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • 1
    http://stackoverflow.com/questions/406361/floating-point-limitations http://stackoverflow.com/questions/286061/python-decimal-place-issues-with-floats –  Jan 18 '09 at 19:41
  • 2
    http://stackoverflow.com/questions/249467/what-is-a-simple-example-of-floating-point-rounding-error –  Jan 18 '09 at 19:42
  • 87
    It is important not to represent currency in float. Floats are not precise. But penny or cent amounts are integers. Therefore integers are the correct way of representing currency. – Davoud Taghawi-Nejad Jul 15 '12 at 22:44
  • 3
    @DavoudTaghawi-Nejad or more to the point... The [Decimal Type](http://docs.python.org/2/library/decimal.html) – Basic Apr 08 '13 at 11:01
  • 12
    Hmm... Are you trying to represent currency? If so, you should not be using floats for dollars. You could probably use floats for pennies, or whatever the smallest common unit of currency you're trying to model happens to be, but the best practice is to use a decimal representation, as HUAGHAGUAH suggested in his answer. – SingleNegationElimination Apr 13 '09 at 03:39
  • 4
    @Basic, it depends(mostly no). Using integers in cents, or pennies is fool prove. Its the industry standard of representing money. If you know what you are doing, have a sound understanding of floating point arithmetic and python's decimal class, you might use decimal. But it depends much of your problem. Do you need arbitrary precision decimals? Or only two digits? If two digits: integer. It keeps you out of trouble. Source I worked in a software consultancy for banking. – Davoud Taghawi-Nejad Apr 17 '14 at 17:56
  • 34
    I'm coming probably too late here, but I wanted to ask, have the developers of Python solved this problem? Because when I do round(13.949999999999999, 2), I simply get 13.95. I've tried it in Python 2.7.6, as well as 3.4. It works. Not sure if 2.7 even was there in 2009. Maybe it's a Python 2.5 thing? – bad_keypoints Sep 22 '15 at 05:51
  • 9
    @bad_keypoints: Yes, the rounding problem has been solved by by Python 2.7.0+. More in [my answer](http://stackoverflow.com/a/35117668/448474) here – hynekcer Jul 29 '16 at 17:55
  • @DavoudTaghawi-Nejad *penny or cent amounts are integers*, not for petrol prices... – gerrit Mar 13 '17 at 14:19
  • 1
    They are still integers, but with a lower base value. 0.5 cent for example would be 500 of denomination 1/1000 cent. – Davoud Taghawi-Nejad Mar 14 '17 at 15:38
  • 2
    Its working for me on python 2.7. Must have been updated – Palak Bansal Sep 10 '20 at 16:43

36 Answers36

2236

You are running into the old problem with floating point numbers that not all numbers can be represented exactly. The command line is just showing you the full floating point form from memory.

With floating point representation, your rounded version is the same number. Since computers are binary, they store floating point numbers as an integer and then divide it by a power of two so 13.95 will be represented in a similar fashion to 125650429603636838/(2**53).

Double precision numbers have 53 bits (16 digits) of precision and regular floats have 24 bits (8 digits) of precision. The floating point type in Python uses double precision to store the values.

For example,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

If you are after only two decimal places (to display a currency value, for example), then you have a couple of better choices:

  1. Use integers and store values in cents, not dollars and then divide by 100 to convert to dollars.
  2. Or use a fixed point number like decimal.
LeBorgne
  • 103
  • 9
Rex Logan
  • 26,248
  • 10
  • 35
  • 48
  • 1
    But, what about when the number is going from 13.95 to let's say 13.90 ? My output will then be 13.9 I would like it to show the zero – Christian Sep 11 '12 at 15:25
  • 42
    @Christian There's a fundamental difference between the value stored and how you _display_ that value. Formatting the output should allow you to add padding as required, as well as adding comma separators, etc. – Basic Apr 08 '13 at 11:03
  • 30
    worth mention that `"%.2f" % round(a,2)` you can put in not only in printf, but also in such things like `str()` – andilabs Nov 01 '13 at 01:15
  • 31
    why is it that people always assume currency on floating-point rounding? sometimes you just want to work with less precision. – worc Jan 11 '14 at 23:56
  • 1
    It should be noted that `"%.2f" %0.245` will output `'0.24'`, i.e. it only rounds up on 6 or greater – sam-6174 Jun 06 '14 at 22:23
  • 1
    @user2426679: You seem not to have understood this answer. Try rounding 0.225 to two decimal places. – John Y Jun 17 '14 at 22:43
  • 3
    Note In the format 0 is positional argument not needed in python 2.7 or 3.1 , I thought it was part of format and got strange results :) ("{:.2f}".format(a) – Alex Punnen Dec 11 '15 at 07:16
  • 1
    @JohnY why then 0.245 rounds to 0.24 while 0.225 rounds correctly? I would like to see 0.245 round to 0.25 – radtek Jun 14 '16 at 17:41
  • 11
    @radtek: You need to understand that the binary value (of type `float`) is just the closest available approximation of the decimal number (that you are familiar with as a human being). There is no such (finitely representable) binary value as 0.245. It simply does not exist, and mathematically **cannot** exist. The binary value which is closest to 0.245 is slightly **less than** 0.245, so naturally it rounds down. Likewise, there is no such thing as 0.225 in binary, but the binary value which is closest to 0.225 is slightly **greater than** 0.225, so naturally it rounds up. – John Y Jun 14 '16 at 19:06
  • @JohnY I wasn't asking for an explanation, just a solution. I think the only solution is to use Decimal type, unless someone can name a better one. – radtek Jun 15 '16 at 19:13
  • 17
    @radtek: You did literally ask for an explanation. The most straightforward solution is indeed to use `Decimal`, and that was one of the solutions presented in this answer. The other was to convert your quantities to integer and use integer arithmetic. Both of these approaches also appeared in other answers and comments. – John Y Jun 15 '16 at 19:45
  • 3
    By the way, since Python 3.6 we can use f-strings: `f"Result is {result:.2f}"` – Andrey Semakin Feb 20 '19 at 12:53
  • how does this one work, if I want to add a string in front for example: print('blabla floatnumber function(x)) – PV8 Jun 27 '19 at 14:00
  • I could not understand correctly why the python store a number and then divide it by another number instead of storing the real value of the number? Why do not we have such a thing in c++ or c# or ...? Why cannot we store 0.0001_0000_0000_0000... for 0.1? – Mahdi Amrollahi Dec 02 '19 at 09:48
  • 2
    @MahdiAmrollahi: Computers have bits. They can't store "real numbers". They just put bits together and interpret them in conventional ways. For integers, it's fairly easy (many bits are a number in base 2). But with only 0 and 1 you can't store "the real value", especially if the real value is an irrational value (e.g. pi). IEEE-754 arithmetic (`float` in Python, `float`/`double` in C/C++/C#) is efficient and "close enough". More precise options exist (`fractions.Fraction`, `decimal.Decimal`; the latter uses a storage format similar to what you're asking for), but they're slower and bigger. – ShadowRanger Dec 12 '20 at 06:48
  • I can't repeat the result. round(a,2) gets 13.95 by python 2.7 and 3.7. – user Sep 08 '21 at 17:42
  • Yes the newer versions of 2.7 and 3.x have auto rounding when they display as a string. This was not the case 14 years ago – Rex Logan Dec 03 '21 at 23:52
  • I realise it's an old answer but rounding twice `"%.2f" % round(a, 2)` seems a dangerous pattern. The classic mistake being to round once and then again with fewer decimal places. Eg mistakenly `"%.1f" % round(a, 2)` might round 1.045 to 1.1 by rounding first 1.045 to 1.05 and then 1.05 to 1.1. Generally this pattern of rounding twice should be avoided. – Philip Couling Jan 01 '23 at 19:55
789

There are new format specifications, String Format Specification Mini-Language:

You can do the same as:

"{:.2f}".format(13.949999999999999)

Note 1: the above returns a string. In order to get as float, simply wrap with float(...):

float("{:.2f}".format(13.949999999999999))

Note 2: wrapping with float() doesn't change anything:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
LeBorgne
  • 103
  • 9
Xolve
  • 22,298
  • 21
  • 77
  • 125
  • 27
    to add commas as well you can `'{0:,.2f}'.format(1333.949999999)` which prints `'1,333.95'`. – Stephen Blum Jun 20 '14 at 02:41
  • @OnurYıldırım: yes, but you can wrap it with `float()`; `float("{0:.2f}".format(13.9499999))` – Jossef Harush Kadouri Aug 17 '14 at 13:22
  • 5
    @JossefHarush you can wrap it with float(), but you haven't gained anything. Now you have a float again, with all the same imprecision. 13.9499999999999 and 13.95 are the same float. – Ned Batchelder Aug 17 '14 at 13:52
  • 4
    @NedBatchelder: i agree that they are equal, but this limits the float to two decimal points :) – Jossef Harush Kadouri Aug 17 '14 at 14:09
  • There's no way to "round" a number. Formatting is just for pretty-printing. If you really need to store the digits (e.g. keeping track of money) use integers. – Neil Oct 07 '17 at 21:41
  • @NeilChowdhury True, I asked me same after writing the answer. Assumption of question is to display float where to two decimal places. – Xolve Oct 08 '17 at 03:43
  • Notice that if you want to format more than one number, you need to increment the integer before the colon: >>> print("{0:.2f} - {0:.2f}".format(.1234, .5678)) 0.12 - 0.12 >>> print("{0:.2f} - {1:.2f}".format(.1234, .5678)) 0.12 - 0.57 – AlejandroVD Nov 15 '17 at 18:33
  • 53
    By the way, since Python 3.6 we can use f-strings: `f"Result is {result:.2f}"` – Andrey Semakin Feb 20 '19 at 12:54
421

The built-in round() works just fine in Python 2.7 or later.

Example:

>>> round(14.22222223, 2)
14.22

Check out the documentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chribsen
  • 6,232
  • 4
  • 26
  • 24
  • 1
    So am I to understand that this is a Python 2.7 fail? Why would such a fundamental function yield different results from v 2.7 to v 3? – Michael M Sep 02 '17 at 23:50
  • 1
    but `round(2.16, 1)` give `2.2` why python just offer a `truncate` func – jiamo Jan 08 '18 at 03:31
  • 2
    For example, if you try to round the value 2.675 to two decimal places, you get this `>>> round(2.675, 2) 2.67` https://docs.python.org/2/tutorial/floatingpoint.html – Melroy van den Berg Nov 06 '18 at 17:41
  • 9
    From Python 3 documentation page: `Note 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.` – Richard Dally May 18 '19 at 22:14
  • 3
    Note that if you try to use this method to print out a number such as 1.00000 it will only print out 1.0, regardless of how many decimal points you specify. – Josh Correia Aug 03 '19 at 16:36
  • @RichardDally Thanks for the much needed information. Can you please explain why _"most decimal fractions can’t be represented exactly as a float"_? – Md. Sabbir Ahmed Dec 12 '20 at 06:57
  • @MichaelM I don't think `round` changed but `print` did. I have a question about it somewhere on this site. – Mark Ransom Jun 14 '23 at 16:05
329

Let me give an example in Python 3.6's f-string/template-string format, which I think is beautifully neat:

>>> f'{a:.2f}'

It works well with longer examples too, with operators and not needing parentheses:

>>> print(f'Completed in {time.time() - start:.2f}s')
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt Fletcher
  • 8,182
  • 8
  • 41
  • 60
179

I feel that the simplest approach is to use the format() function.

For example:

a = 13.949999999999999
format(a, '.2f')

13.95

This produces a float number as a string rounded to two decimal points.

Armali
  • 18,255
  • 14
  • 57
  • 171
grant zukowski
  • 1,894
  • 1
  • 13
  • 10
101

Most numbers cannot be exactly represented in floats. If you want to round the number because that's what your mathematical formula or algorithm requires, then you want to use round. If you just want to restrict the display to a certain precision, then don't even use round and just format it as that string. (If you want to display it with some alternate rounding method, and there are tons, then you need to mix the two approaches.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

And lastly, though perhaps most importantly, if you want exact math then you don't want floats at all. The usual example is dealing with money and to store 'cents' as an integer.

100

Use

print"{:.2f}".format(a)

instead of

print"{0:.2f}".format(a)

Because the latter may lead to output errors when trying to output multiple variables (see comments).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexey Antonenko
  • 2,389
  • 1
  • 18
  • 18
  • 1
    I mean, print"{0:.2f} {0:.2f}".format(a, b) will lead to mistake in output - it will output 'a' value twice. While print"{:.2f} {:.2f}".format(a, b) will output 'a' and 'b' values. – Alexey Antonenko Feb 01 '18 at 17:30
  • 2
    For Python 3, you just need to add brackets print(...). And within them all I wrote is right. – Alexey Antonenko Feb 01 '18 at 17:31
  • 3
    You would be after print("{0:.2f} {1:.2f}".format(a, b)) if you have two variables – Hovo Feb 10 '18 at 23:12
71

Try the code below:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ax003d
  • 3,278
  • 29
  • 26
  • But be cautioned, value of a is still an imprecise float. Take a look here - http://repl.it/LJs (Click "Run Session" on the top of the Right section). – lifebalance Oct 02 '13 at 19:23
  • 3
    If you go with this approach, you should add a 0.5 for a more accurate representation. int(a * 100 + 0.5) / 100.0 ; Using math.ceil is another option. – arhuaco Nov 08 '13 at 00:11
  • If a member is going to down vote this answer, please provide an explanation, so that we can understand what's wrong with this approach. For the reason mentioned by `OriolJ`, I find this to be the best answer. – Shashank Sawant Jun 08 '14 at 04:55
  • 3
    @ShashankSawant: Well, for one thing, the answer as presented does not round, it truncates. The suggestion to add half at the end will round, but then there is no benefit to doing this over just using the `round` function in the first place. For another thing, because this solution still uses floating point, the OP's original problem remains, even for the "corrected" version of this "solution". – John Y Jun 17 '14 at 22:54
  • 3
    -1, this is just an unnecessary reimplementation of the `round` function (which was used in the question). – interjay Sep 12 '14 at 22:55
  • 5
    @interjay which is necessary if the `round()` doesn't work as the OP mentioned. – Pithikos Feb 18 '15 at 13:28
  • This works fine in Python 3, you just need to make sure you include the .0 in the denominator – duhaime Mar 05 '18 at 00:08
  • @Pithikos `round()` works just fine, and this code doesn't work any better. The problem is that Python uses binary floating point numbers, and the closest you can get to `13.95` is `13.949999999999999`. If you see code that generates any other number, it's because more rounding is applied when converting to a string. See [Is floating point math broken?](https://stackoverflow.com/q/588004/5987). – Mark Ransom Dec 18 '19 at 23:00
71

TLDR ;)

The rounding problem of input and output has been solved definitively by Python 3.1 and the fix is backported also to Python 2.7.0.

Rounded numbers can be reversibly converted between float and string back and forth:
str -> float() -> repr() -> float() ... or Decimal -> float -> str -> Decimal

>>> 0.3
0.3
>>> float(repr(0.3)) == 0.3
True

A Decimal type is not necessary for storage anymore.

Results of arithmetic operations must be rounded again because rounding errors could accumulate more inaccuracy than that is possible after parsing one number. That is not fixed by the improved repr() algorithm (Python >= 3.1, >= 2.7.0):

>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1, 0.2, 0.3
(0.1, 0.2, 0.3)

The output string function str(float(...)) was rounded to 12 valid digits in Python < 2.7x and < 3.1, to prevent excessive invalid digits similar to unfixed repr() output. That was still insufficientl after subtraction of very similar numbers and it was too much rounded after other operations. Python 2.7 and 3.1 use the same length of str() although the repr() is fixed. Some old versions of Numpy had also excessive invalid digits, even with fixed Python. The current Numpy is fixed. Python versions >= 3.2 have the same results of str() and repr() function and also output of similar functions in Numpy.


Test

import random
from decimal import Decimal
for _ in range(1000000):
    x = random.random()
    assert x == float(repr(x)) == float(Decimal(repr(x)))  # Reversible repr()
    assert str(x) == repr(x)
    assert len(repr(round(x, 12))) <= 14         # no excessive decimal places.

Documentation

See the Release notes Python 2.7 - Other Language Changes the fourth paragraph:

Conversions between floating-point numbers and strings are now correctly rounded on most platforms. These conversions occur in many different places: str() on floats and complex numbers; the float and complex constructors; numeric formatting; serializing and de-serializing floats and complex numbers using the marshal, pickle and json modules; parsing of float and imaginary literals in Python code; and Decimal-to-float conversion.

Related to this, the repr() of a floating-point number x now returns a result based on the shortest decimal string that’s guaranteed to round back to x under correct rounding (with round-half-to-even rounding mode). Previously it gave a string based on rounding x to 17 decimal digits.

The related issue


More information: The formatting of float before Python 2.7 was similar to the current numpy.float64. Both types use the same 64 bit IEEE 754 double precision with 52 bit mantissa. A big difference is that np.float64.__repr__ is formatted frequently with an excessive decimal number so that no bit can be lost, but no valid IEEE 754 number exists between 13.949999999999999 and 13.950000000000001. The result is not nice and the conversion repr(float(number_as_string)) is not reversible with numpy. On the other hand: float.__repr__ is formatted so that every digit is important; the sequence is without gaps and the conversion is reversible. Simply: If you perhaps have a numpy.float64 number, convert it to normal float in order to be formatted for humans, not for numeric processors, otherwise nothing more is necessary with Python 2.7+.

hynekcer
  • 14,942
  • 6
  • 61
  • 99
  • Why downvoted? The question was about Python `float` (double precision) and normal `round`, not about numpy.double and its conversion to string. Plain Python rounding really can not be done better than in Python 2.7. The most of answers has been written before 2.7, but they are obsoleted, though they were very good originally. This is the reason of my answer. – hynekcer Apr 15 '16 at 11:02
  • 53 bits when you include the "hidden bit", which is implicitly `1`, except during "gradual underflow". – Rick James May 17 '17 at 04:16
  • It's not round's fault, it's the display fault. – Rick James May 17 '17 at 04:22
  • Yes, it's well known. I miss however a context if you object to something in Python 2.7 Release notes or in my text or to nothing at all. It is more complicated than was necessary the purpose of this question. It should be added that also conversion from string to float has been fixed in Python 2.7 due to [rounding bug on certain 32-bit Intel chips](https://bugs.python.org/issue2937) and that "The round() function is also **now** correctly rounded." ([Release notes - 3.1 features backported to 2.7](https://docs.python.org/2.7/whatsnew/2.7.html#python-3-1-features)). Can you agree? – hynekcer May 17 '17 at 09:26
  • 1
    Oops, that was `a*b` vs `b*a`. Thanks for the links -- Nostalgia. – Rick James May 17 '17 at 20:11
  • The sample code fails for both Python 2.7.13 and Python 3.5.3. – Jérôme Apr 16 '18 at 08:50
  • @Jérôme Thanks. Fixed now. I was a typo `x` instead of `y` when I combined two tests into this example for different order of magnitude. – hynekcer Apr 16 '18 at 18:46
66

Use:

float_number = 12.234325335563
round(float_number, 2)

This will return;

12.23

Explanation:

The round function takes two arguments; The number to be rounded and the number of decimal places to be returned. Here I returned two decimal places.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Irfan wani
  • 4,084
  • 2
  • 19
  • 34
  • 2
    But how did you get an additional 0 to show up if we have say, 0.093. This is giving me 0.1 as the answer – Naman Jain Nov 25 '20 at 00:40
  • If you return 2 decimal places or in general 1 place more than the number of zeroes present in the decimal part on left side, then you will get the correct result as you want.e.g, if you apply simply my answer to the number 0.093, it will return 0.09 but if you want to get only 1 decimal place, then of course, it will return 0.1 as 0.0 is completely wrong.(and my code works in the same way. Maybe you want to get only 1 decimal place. If you want to get more accurate results, you must have to increase the number of decimal places.) – Irfan wani Nov 25 '20 at 09:53
  • It's not true that it will return decimal, according to the documentation ` The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as the number. ndigits may be negative.` – Arar Mar 09 '21 at 01:53
  • All these bogus up votes. Your answer just repeats the code the OP posted when asking the question a decade ago. The OP knows the round function. You didn't solve his problem with it at all. (The problem doesn't even exist today.) – aamarks Jun 29 '21 at 17:25
  • This doesn't work for larger numbers. Round doesn't behave like what people want. We want a decimal format not a round. 99.9999999987 should not turn into 100 it should be 99.99. That is the issue people want resolved. Simple small math is a no brainer. – Eric Dec 09 '21 at 13:45
58

You can modify the output format:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
56

With Python < 3 (e.g. 2.6 or 2.7), there are two ways to do so.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

But note that for Python versions above 3 (e.g. 3.2 or 3.3), option two is preferred.

For more information on option two, I suggest this link on string formatting from the Python documentation.

And for more information on option one, this link will suffice and has information on the various flags.

Reference: Convert floating point number to a certain precision, and then copy to string

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
A.J.
  • 8,557
  • 11
  • 61
  • 89
  • How do you represent an integer? If I use "{i3}".format(numvar) I get an error. – skytux Dec 12 '13 at 15:29
  • This is what I mean: If `numvar=12.456`, then `"{:.2f}".format(numvar)` yields `12.46` but `"{:2i}".format(numvar)` gives an error and I'm expecting `12`. – skytux Dec 12 '13 at 15:47
44

You can use format operator for rounding the value up to two decimal places in Python:

print(format(14.4499923, '.2f')) // The output is 14.45
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Asad Manzoor
  • 1,355
  • 15
  • 18
35

As Matt pointed out, Python 3.6 provides f-strings, and they can also use nested parameters:

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

which will display result: 2.35

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
toto_tico
  • 17,977
  • 9
  • 97
  • 116
31

In Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output
Shashank Singh
  • 719
  • 6
  • 11
  • 1
    This doesn't help at all. `output` has the *exact same* value as `a`, so you might as well have written `print a` instead of `print output` in the last line. – Mark Dickinson May 26 '18 at 06:12
  • @MarkDickinson Could you please try again. Because It is running as expected in my compiler. – Shashank Singh Sep 23 '18 at 08:07
  • 1
    You're missing my point. Yes, your code prints `13.95`. But so does `print a`, for this particular value of `a`, in Python 2.7, so it's not really clear what the point of the formatting step was. – Mark Dickinson Sep 23 '18 at 11:13
  • @MarkDickinson I have edited the code. I agree that 'print a' does print the same value as "print output". But if you compare "a==output", the result will be "False" because formatting step does round off the floating value "a" to two decimal points. – Shashank Singh Sep 23 '18 at 11:45
  • 1
    Did you actually try `a == output` for the code you show? It gives `True` for me, and I suspect it does for you, too. – Mark Dickinson Sep 23 '18 at 11:46
  • @MarkDickinson For `a=13.949999999999999`, I am getting _True_. For `a=13.9499999`, I am getting _False_. I am a bit confused now!!! – Shashank Singh Sep 23 '18 at 11:58
28

We multiple options to do that:

Option 1:

x = 1.090675765757
g = float("{:.2f}".format(x))
print(g)

Option 2: The built-in round() supports Python 2.7 or later.

x = 1.090675765757
g = round(x, 2)
print(g)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    The question specifically says that the round method does not do what he wants. Check [this answer](https://stackoverflow.com/a/455634/6580047) for more info on why is that – Gustavo Kawamoto Oct 05 '20 at 01:43
24

The Python tutorial has an appendix called Floating Point Arithmetic: Issues and Limitations. Read it. It explains what is happening and why Python is doing its best. It has even an example that matches yours. Let me quote a bit:

>>> 0.1
0.10000000000000001

you may be tempted to use the round() function to chop it back to the single digit you expect. But that makes no difference:

>>> round(0.1, 1)
0.10000000000000001

The problem is that the binary floating-point value stored for “0.1” was already the best possible binary approximation to 1/10, so trying to round it again can’t make it better: it was already as good as it gets.

Another consequence is that since 0.1 is not exactly 1/10, summing ten values of 0.1 may not yield exactly 1.0, either:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

One alternative and solution to your problems would be using the decimal module.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nosklo
  • 217,122
  • 57
  • 293
  • 297
15

Use combination of Decimal object and round() method.

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')
Jonathan L
  • 9,552
  • 4
  • 49
  • 38
13

It's doing exactly what you told it to do and is working correctly. Read more about floating point confusion and maybe try decimal objects instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
HUAGHAGUAH
  • 1,836
  • 10
  • 7
11

For Raw Python:

For float to string converted 2 decimal points:

a = 13.949999999999999
format(a, '.2f')

For float to float converted 2 decimal points:

a = 13.949999999999999
round(float(a), 2)
or
float(format(a, '.2f'))
MD. SHIFULLAH
  • 913
  • 10
  • 16
10
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Results:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
weaming
  • 5,605
  • 1
  • 23
  • 15
  • Instead of `Decimal` can we return `float`? like: `def round_float(v, ndigits=2) -> float: d = Decimal(v); v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits)); return float(v_str)` – alper Jul 18 '21 at 10:01
  • @alper you can return whatever you prefer to – weaming Jul 19 '21 at 16:54
8

It's simple like:

  1. use decimal module for fast correctly-rounded decimal floating point arithmetic:

     d = Decimal(10000000.0000009)
    

    to achieve rounding:

     d.quantize(Decimal('0.01'))
    

    will result with Decimal('10000000.00')

  2. make the above DRY:

    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))
    

    or

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
    

PS: critique of others: formatting is not rounding.

Sławomir Lenart
  • 7,543
  • 4
  • 45
  • 61
8

Use a lambda function like this:

arred = lambda x,n : x*(10**n)//1/(10**n)

This way you could just do:

arred(3.141591657, 2)

and get

3.14
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gustavo Mirapalheta
  • 931
  • 2
  • 11
  • 25
8

The simple solution is here

value = 5.34343
rounded_value = round(value, 2) # 5.34
Praveen Kumar
  • 849
  • 8
  • 8
  • 2
    There's a lot of unnecessary stuff here. `8/3` is already of type `float`, so the `float` call does nothing useful. And calling dunder methods directly is a bit odd - instead, simply call the function that delegates to those dunder methods. So a better way to spell the first line is simply `value = round(8/3, 2)`. And at that point you're not really adding anything that isn't already in other answers. – Mark Dickinson Feb 19 '22 at 19:03
  • Sorry for the irrelevant answer. I thought it is the correct method. Also, In the question section, he mentioned that the round method was not working and so I didn't check it. – Praveen Kumar Feb 19 '22 at 20:41
7

For fixing the floating point in type-dynamic languages such as Python and JavaScript, I use this technique

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

You can also use Decimal as following:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Siamand
  • 1,080
  • 10
  • 19
  • 1
    `getcontext().prec = 6` works for just the scope of the function or all places? – Julio Marins Oct 04 '17 at 20:12
  • 1
    Contexts are environments for arithmetic operations. They govern precision, set rules for rounding, determine which signals are treated as exceptions, and limit the range for exponents. Each thread has its own current context @JulioMarins – Siamand Oct 04 '17 at 20:32
7
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54

MikeL
  • 5,385
  • 42
  • 41
6

Here is the simple solution using the format function.

float(format(num, '.2f'))

Note: We are converting numbers to float, because the format method is returning a string.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
5

If you want to handle money, use the Python decimal module:

from decimal import Decimal, ROUND_HALF_UP

# 'amount' can be integer, string, tuple, float, or another Decimal object
def to_money(amount) -> Decimal:
    money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
    return money
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yogesh Yadav
  • 4,557
  • 6
  • 34
  • 40
  • I tried to use this with a column of a DateFrame. got the message: TypeError: conversion from Series to Decimal is not supported – Steve Maguire Feb 05 '22 at 16:35
4
lambda x, n:int(x*10^n + 0.5)/10^n

has worked for me for many years in many languages.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
3

To round a number to a resolution, the best way is the following one, which can work with any resolution (0.01 for two decimals or even other steps):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
iblasi
  • 1,269
  • 9
  • 21
  • doesn't work for me on python 3.4.3 and numpy 1.9.1 ? >>> import numpy as np >>> res = 0.01 >>> value = 0.184 >>> np.round(value/res) * res 0.17999999999999999 – szeitlin Apr 11 '16 at 16:34
  • 1
    Looking for documentation I see the problem comes from ```numpy.round``` accuracy/precision. So it requires to define it as int before multiplication with resolution. I updated the code. Thank you for that! – iblasi Apr 13 '16 at 16:28
  • The only necessary is to convert `numpy.float64` result of np.round to `float` or simply to use `round(value, 2)`. No valid IEEE 754 number exists between 13.949999999999999 (= 1395 / 100.) and 3.950000000000001 (= 1395 * .01). Why do you think that your method is the best? The original value 13.949999999999999289 (= value = round(value, 2)) is even more exact than your 13.95000000000000178 (printed by np.float96). More info also for numpy is now added to [my answer](http://stackoverflow.com/a/35117668/448474) that you probably downvoted by mistake. It wasn't about numpy originally. – hynekcer Apr 15 '16 at 13:04
  • @hynekcer I do not think that my answer is the best. Just wanted to add an example of limit float to n decimals but the nearest of a defined resolution. I checked as you said, that instead of ```int```you can also use ```float```for @szeitlin example. Thank you for your extra comment. (Sorry but I did not downvote you) – iblasi Apr 15 '16 at 20:49
  • Adding whole new dependency for numeric processing (pandas) is the "best way"? – Hejazzman Apr 18 '19 at 14:13
3

The answers I saw didn't work with the float(52.15) case. After some tests, there is the solution that I'm using:

import decimal
        
def value_to_decimal(value, decimal_places):
    decimal.getcontext().rounding = decimal.ROUND_HALF_UP  # define rounding method
    return decimal.Decimal(str(float(value))).quantize(decimal.Decimal('1e-{}'.format(decimal_places)))

(The conversion of the 'value' to float and then string is very important, that way, 'value' can be of the type float, decimal, integer or string!)

Hope this helps anyone.

NMC
  • 1,210
  • 10
  • 14
0

Just use this function and pass bytes as an input to it:

def getSize(bytes):
    kb = round(bytes/1024, 4)
    mb = round(kb/1024, 4)
    gb = round(mb/1024, 4)
    if(gb > 1):
        return str(gb) + " GB"
    elif(mb > 1):
        return str(mb) + " MB"
    else:
        return str(kb) + " KB"

This is the easiest way I could get to convert the data size from bytes to KB, MB or GB dynamically.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
heyom
  • 322
  • 2
  • 7
0

One-liner function to print percentage:

k - the numerator

n - the denominator

'%.2f' - means you want a precision of 2 decimal places

*100 - turns the number from a decimal to a percentage

   percentage = lambda k, n: '%.2f' % (k/n*100)

   - equivalent to-

   def percentage(k,n):
       return '%.2f' % (k/n*100)

percentage(1,3)

output -> '33.33'

Mark Dickinson
  • 29,088
  • 9
  • 83
  • 120
DonCarleone
  • 544
  • 11
  • 20
0

To calculate I use a function to truncate value maybe help to you

import math


def truncate(number, digits) -> float:
    stepper = pow(10.0, digits)
    return math.trunc(stepper * number) / stepper


print(truncate((0.1 + 0.2), 2))
-4

transform a to float first:

round(float(a), 2)
-18

The method I use is that of string slicing. It's relatively quick and simple.

First, convert the float to a string, the choose the length you would like it to be.

float = str(float)[:5]

In the single line above, we've converted the value to a string, then kept the string only to its first four digits or characters (inclusive).

Hope that helps!

tdh
  • 884
  • 1
  • 11
  • 22
  • 2
    Please don't post identical answers to multiple questions. – vaultah Dec 31 '15 at 08:18
  • 20
    WOW... tdh... Please never make any accounting software... What happens if the number happen to be 113.94 ?? this would result in 113.9 ... leaving 0.04 missing.... Also this already has answers from over 5 years ago.... – Angry 84 Jan 08 '16 at 03:33