85

Using Python 2.7 how do I round my numbers to two decimal places rather than the 10 or so it gives?

print "financial return of outcome 1 =","$"+str(out1)
PolyGeo
  • 1,340
  • 3
  • 26
  • 59
RCN
  • 851
  • 1
  • 6
  • 3
  • 3
    This could be a can of worms. Are you storing financial data in a floating point variable and now want to round that? *Exact* rounding is not possible in most cases. You might want to use integers or `Decimal`s, depending on what you're actually trying to do. – Tim Pietzcker Jul 04 '13 at 12:57
  • Learn about format specifiers. You can directly print float values, without converting them to strings. – John Doe Jul 04 '13 at 13:11

9 Answers9

203

Use the built-in function round():

>>> round(1.2345,2)
1.23
>>> round(1.5145,2)
1.51
>>> round(1.679,2)
1.68

Or built-in function format():

>>> format(1.2345, '.2f')
'1.23'
>>> format(1.679, '.2f')
'1.68'

Or new style string formatting:

>>> "{:.2f}".format(1.2345)
'1.23
>>> "{:.2f}".format(1.679)
'1.68'

Or old style string formatting:

>>> "%.2f" % (1.679)
'1.68'

help on round:

>>> print round.__doc__
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.
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 2
    The string formatting method is useful when working with Decimals. E.g. `Decimal("{:.2f}".format(val))` – Patch Rick Walsh May 02 '14 at 08:27
  • @PatchRickWalsh Or simply `Decimal(format(val, '.2f'))`. – Ashwini Chaudhary May 02 '14 at 08:39
  • 9
    Cool! I didn't know about that format builtin. After exploring more, I think this is the most accurate way of rounding if floating point errors are absolutely not acceptable: `Decimal('123.345').quantize(Decimal('1.00'), rounding=decimal.ROUND_HALF_UP)` gives you `Decimal('123.35')`. On the other hand `Decimal(format(Decimal('123.345'), '.2f'))` gives you `Decimal('123.34')` because the binary representation of 123.345 is less than 123.345. – Patch Rick Walsh May 02 '14 at 09:16
50

Since you're talking about financial figures, you DO NOT WANT to use floating-point arithmetic. You're better off using Decimal.

>>> from decimal import Decimal
>>> Decimal("33.505")
Decimal('33.505')

Text output formatting with new-style format() (defaults to half-even rounding):

>>> print("financial return of outcome 1 = {:.2f}".format(Decimal("33.505")))
financial return of outcome 1 = 33.50
>>> print("financial return of outcome 1 = {:.2f}".format(Decimal("33.515")))
financial return of outcome 1 = 33.52

See the differences in rounding due to floating-point imprecision:

>>> round(33.505, 2)
33.51
>>> round(Decimal("33.505"), 2)  # This converts back to float (wrong)
33.51
>>> Decimal(33.505)  # Don't init Decimal from floating-point
Decimal('33.50500000000000255795384873636066913604736328125')

Proper way to round financial values:

>>> Decimal("33.505").quantize(Decimal("0.01"))  # Half-even rounding by default
Decimal('33.50')

It is also common to have other types of rounding in different transactions:

>>> import decimal
>>> Decimal("33.505").quantize(Decimal("0.01"), decimal.ROUND_HALF_DOWN)
Decimal('33.50')
>>> Decimal("33.505").quantize(Decimal("0.01"), decimal.ROUND_HALF_UP)
Decimal('33.51')

Remember that if you're simulating return outcome, you possibly will have to round at each interest period, since you can't pay/receive cent fractions, nor receive interest over cent fractions. For simulations it's pretty common to just use floating-point due to inherent uncertainties, but if doing so, always remember that the error is there. As such, even fixed-interest investments might differ a bit in returns because of this.

Ronan Paixão
  • 8,297
  • 1
  • 31
  • 27
5

You can use str.format(), too:

>>> print "financial return of outcome 1 = {:.2f}".format(1.23456)
financial return of outcome 1 = 1.23
TerryA
  • 58,805
  • 11
  • 114
  • 143
4

When working with pennies/integers. You will run into a problem with 115 (as in $1.15) and other numbers.

I had a function that would convert an Integer to a Float.

...
return float(115 * 0.01)

That worked most of the time but sometimes it would return something like 1.1500000000000001.

So I changed my function to return like this...

...
return float(format(115 * 0.01, '.2f'))

and that will return 1.15. Not '1.15' or 1.1500000000000001 (returns a float, not a string)

I'm mostly posting this so I can remember what I did in this scenario since this is the first result in google.

teewuane
  • 5,524
  • 5
  • 37
  • 43
  • As pointed out in another answer, for financial data use decimal numbers, not floats. – Bruno Le Floch Mar 20 '17 at 03:24
  • 1
    I ended up converting most everything to integers. It seems to be much easier to work with. However, I wasn't doing anything that deals with fractions of pennies. – teewuane Mar 22 '17 at 00:09
2

The best, I think, is to use the format() function:

>>> print("financial return of outcome 1 = $ " + format(str(out1), '.2f'))
// Should print: financial return of outcome 1 = $ 752.60

But I have to say: don't use round or format when working with financial values.

  • `format` requires non-string for f format. If not you got a ValueError. The correct code is: `format(out1, '.2f')` without casting to string – danius Feb 20 '18 at 23:53
2

When we use the round() function, it will not give correct values.

you can check it using, round (2.735) and round(2.725)

please use

import math
num = input('Enter a number')
print(math.ceil(num*100)/100)
Midhun M M
  • 21
  • 3
1
print "financial return of outcome 1 = $%.2f" % (out1)
John Doe
  • 423
  • 3
  • 10
0

A rather simple workaround is to convert the float into string first, the select the substring of the first four numbers, finally convert the substring back to float. For example:

>>> out1 = 1.2345
>>> out1 = float(str(out1)[0:4])
>>> out1

May not be super efficient but simple and works :)

Shan Niz
  • 59
  • 1
  • 4
  • 2
    This method is very unreliable. If your value has more than one digit before the decimal point you don't get the two wanted decimal places. Same problem with a negative number. – André Kuhlmann Apr 10 '18 at 16:15
0

Rounding up to the next 0.05, I would do this way:

def roundup(x):
    return round(int(math.ceil(x / 0.05)) * 0.05,2)
Lucas VL
  • 9
  • 1