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?.
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:
Answered 2023-09-20 20:33:37
"%.2f" % round(a,2)
you can put in not only in printf, but also in such things like str()
- anyone 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. - anyone 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. - anyone 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
Answered 2023-09-20 20:33:37
'{0:,.2f}'.format(1333.949999999)
which prints '1,333.95'
. - anyone float()
; float("{0:.2f}".format(13.9499999))
- anyone f"Result is {result:.2f}"
- anyone The built-in round()
works just fine in Python 2.7 or later.
Example:
>>> round(14.22222223, 2)
14.22
Check out the documentation.
Answered 2023-09-20 20:33:37
round(2.16, 1)
give 2.2
why python just offer a truncate
func - anyone >>> round(2.675, 2) 2.67
docs.python.org/2/tutorial/floatingpoint.html - anyone 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.
- anyone 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')
Answered 2023-09-20 20:33:37
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.
Answered 2023-09-20 20:33:37
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.
Answered 2023-09-20 20:33:37
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).
Answered 2023-09-20 20:33:37
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
Answered 2023-09-20 20:33:37
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". - anyone round
function (which was used in the question). - anyone round()
doesn't work as the OP mentioned. - anyone 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.
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.
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
andjson
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.
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+.
Answered 2023-09-20 20:33:37
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. - anyone 1
, except during "gradual underflow". - anyone a*b
vs b*a
. Thanks for the links -- Nostalgia. - anyone 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.
Answered 2023-09-20 20:33:37
You can modify the output format:
>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Answered 2023-09-20 20:33:37
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
Answered 2023-09-20 20:33:37
numvar=12.456
, then "{:.2f}".format(numvar)
yields 12.46
but "{:2i}".format(numvar)
gives an error and I'm expecting 12
. - anyone 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
Answered 2023-09-20 20:33:37
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
Answered 2023-09-20 20:33:37
In Python 2.7:
a = 13.949999999999999
output = float("%0.2f"%a)
print output
Answered 2023-09-20 20:33:37
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. - anyone 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. - anyone a == output
for the code you show? It gives True
for me, and I suspect it does for you, too. - anyone 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)
Answered 2023-09-20 20:33:37
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 to1/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 exactly1/10
, summing ten values of0.1
may not yield exactly1.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.
Answered 2023-09-20 20:33:37
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')
Answered 2023-09-20 20:33:37
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.
Answered 2023-09-20 20:33:37
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'))
Answered 2023-09-20 20:33:37
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'
Answered 2023-09-20 20:33:37
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)
- anyone The simple solution is here
value = 5.34343
rounded_value = round(value, 2) # 5.34
Answered 2023-09-20 20:33:37
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. - anyone 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
Answered 2023-09-20 20:33:37
def
. Creating a lambda
here is really just showing off for no particular gain. - anyone It's simple like:
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')
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.
Answered 2023-09-20 20:33:37
orig_float = 232569 / 16000.0
14.5355625
short_float = float("{:.2f}".format(orig_float))
14.54
Answered 2023-09-20 20:33:37
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')
Answered 2023-09-20 20:33:37
getcontext().prec = 6
works for just the scope of the function or all places? - anyone 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.
Answered 2023-09-20 20:33:37
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
Answered 2023-09-20 20:33:37
lambda x, n:int(x*10^n + 0.5)/10^n
has worked for me for many years in many languages.
Answered 2023-09-20 20:33:37
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
Answered 2023-09-20 20:33:37
numpy.round
accuracy/precision. So it requires to define it as int before multiplication with resolution. I updated the code. Thank you for that! - anyone 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 that you probably downvoted by mistake. It wasn't about numpy originally. - anyone int
you can also use float
for @szeitlin example. Thank you for your extra comment. (Sorry but I did not downvote you) - anyone