Limiting floats to two decimal points

PythonFloating PointRoundingPrecision

Python Problem Overview


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

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

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

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

Solution 3 - Python

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

Example:

>>> round(14.22222223, 2)
14.22

Check out the documentation.

Solution 4 - Python

Nobody here seems to have mentioned it yet, so 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 parens:

>>> print(f'Completed in {time.time() - start:.2f}s')

Solution 5 - Python

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.

Solution 6 - Python

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.

Solution 7 - Python

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).

Solution 8 - Python

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

Solution 9 - Python

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+.

Solution 10 - Python

float_number = 12.234325335563
round(float_number, 2)

This will return;

12.23

Explanation:

round function takes two arguments; Number to be rounded and the number of decimal places to be returned.Here i returned 2 decimal places.

Solution 11 - Python

You can modify the output format:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95

Solution 12 - Python

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: https://stackoverflow.com/questions/15263597/convert-floating-point-number-to-certain-precision-then-copy-to-string

Solution 13 - Python

You can use format operator for rounding the value up to 2 decimal places in python:

print(format(14.4499923, '.2f')) // output is 14.45

Solution 14 - Python

In Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output

Solution 15 - Python

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

Solution 16 - Python

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)

Solution 17 - Python

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.

Solution 18 - Python

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')

Solution 19 - Python

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.

Solution 20 - Python

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'

Solution 21 - Python

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')

Solution 22 - Python

orig_float = 232569 / 16000.0

>14.5355625

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

>14.54

Solution 23 - Python

What about 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

Solution 24 - Python

It's simple like 1,2,3:

  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 results with Decimal('10000000.00')

  1. make 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)
  1. upvote this answer :)

PS: critique of others: formatting is not rounding.

Solution 25 - Python

Here is the Simple Solution Using format Function.

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

> NOTE: We are converting numbers to float because format method is > returning string.

Solution 26 - Python

If you want to handle money, use 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

Solution 27 - Python

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

Solution 28 - Python

lambda x,n:int(x*10^n+.5)/10^n has worked for me for many years in many languages.

Solution 29 - Python

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.

Solution 30 - Python

The simple solution is here

value = 5.34343
rounded_value = round(value, 2) # 5.34

Solution 31 - Python

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

Solution 32 - Python

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!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkevinView Question on Stackoverflow
Solution 1 - PythonRex LoganView Answer on Stackoverflow
Solution 2 - PythonXolveView Answer on Stackoverflow
Solution 3 - PythonchribsenView Answer on Stackoverflow
Solution 4 - PythonMatt FletcherView Answer on Stackoverflow
Solution 5 - Pythongrant zukowskiView Answer on Stackoverflow
Solution 6 - PythonRoger PateView Answer on Stackoverflow
Solution 7 - PythonAlexey AntonenkoView Answer on Stackoverflow
Solution 8 - Pythonax003dView Answer on Stackoverflow
Solution 9 - PythonhynekcerView Answer on Stackoverflow
Solution 10 - PythonIrfan waniView Answer on Stackoverflow
Solution 11 - PythonGreg HewgillView Answer on Stackoverflow
Solution 12 - PythonA.J.View Answer on Stackoverflow
Solution 13 - PythonAsad ManzoorView Answer on Stackoverflow
Solution 14 - PythonShashank SinghView Answer on Stackoverflow
Solution 15 - Pythontoto_ticoView Answer on Stackoverflow
Solution 16 - PythonpassionatedevopsView Answer on Stackoverflow
Solution 17 - PythonnoskloView Answer on Stackoverflow
Solution 18 - PythonJonathan LView Answer on Stackoverflow
Solution 19 - PythonHUAGHAGUAHView Answer on Stackoverflow
Solution 20 - PythonweamingView Answer on Stackoverflow
Solution 21 - PythonSiamandView Answer on Stackoverflow
Solution 22 - PythonMikeLView Answer on Stackoverflow
Solution 23 - PythonGustavo MirapalhetaView Answer on Stackoverflow
Solution 24 - PythonSławomir LenartView Answer on Stackoverflow
Solution 25 - PythonShoaib Muhammad ArifView Answer on Stackoverflow
Solution 26 - PythonYogesh YadavView Answer on Stackoverflow
Solution 27 - PythoniblasiView Answer on Stackoverflow
Solution 28 - PythonRay TayekView Answer on Stackoverflow
Solution 29 - PythonNMCView Answer on Stackoverflow
Solution 30 - PythonPraveen KumarView Answer on Stackoverflow
Solution 31 - PythonheyomView Answer on Stackoverflow
Solution 32 - PythontdhView Answer on Stackoverflow