Round an answer to 2 decimal places in Python

Question:

The issue i am having is my rounding my results to 2 decimal places. My app gets the right results, however, i am having difficulty making the app round to the nearest decimal as you would with currency

cost = input("nEnter the 12 month cost of the Order: ")
cost = float(cost)

print("n12 Month Cost:",
  cost * 1,"USD")
print("6 Month Cost:",
  cost * 0.60,"USD")
print("3 Month Cost:",
  cost * 0.36,"USD")

so for example if the 12 month price is $23, the 6 month price is 13.799999999999999 but i want it to show 13.80

I’ve looked around google and how to round a number but couldn’t find much help on rounding a result.

Asked By: python_newb

||

Answers:

A classic way is to multiply by 100, add 0.5 (this is to round) and int() the result. Now you have the number of rounded cents, divide by 100 again to get back the rounded float.

cost = 5.5566
cost *= 100 # cost = 555.66
cost += 0.5 # cost = 556.16
cost = int(cost) # cost = 556
cost /= float(100) # cost =  5.56

cost = 5.4444
cost = int(( cost * 100 ) + 0.5) / float(100) # cost = 5.44
Answered By: nair.ashvin

You should use a format specifier:

print("6 Month Cost: %.2fUSD" % (cost * .6))

Even better, you shouldn’t rely on floating point numbers at all and use the decimal module instead, which gives you arbitrary precision and much more control over the rounding method:

from decimal import Decimal, ROUND_HALF_UP
def round_decimal(x):
  return x.quantize(Decimal(".01"), rounding=ROUND_HALF_UP)

cost = Decimal(input("Enter 12 month cost: "))
print("6 Month Cost: ", round_decimal(cost * Decimal(".6")))
Answered By: Niklas B.

If you just want it to print, string formatting will work:

print("n12 Month Cost:%.2f USD"%(cost*1))
Answered By: ebarr

If you just want to have it as a string, format can help:

format(cost, '.2f')

This function returns a string that is formated as defined in the second parameter. So if cost contains 3.1418 the code above returns the string ‘3.14’.

Answered By: anhoppe

In some countries cents are allowed to be only multiple of 5. So, f{money:.2f'} just cuts the extra digits but a further rounding process to the nearest multiple of 5 is needed.

For instance 1.233333 will be formatted to 1.23 and then rounded to the closest multiple of 5, 1.25. Or, 1.27 will become 1.25.

Here my solution based on string manipulation

def cround(x:float) -> float:
    """Currency rounder"""
    # round to 2 decimal places
    s = f"{x:.2f}"
    # round to 5 or 0 cent
    i, dot, d = s.partition('.')
    d1, d2 = d
    # check last digit
    if d2 in "05": #    stay the same
        return float(s)
    elif d2 in "12": #  round down
        d = d1 + "0"
    elif d2 in "67": #  round down
        d = d1 + "5"
    elif d2 in "34": #  round up
        d = d1 + "5"
    elif d2 in "89": #  round up
        d2 = "0"
        if int(d1) + 1 < 9:
            d = str(int(d1) + 1) + '0'
        else:
            d = '00'
            i = str(int(i) + 1)      
      
    return float(''.join([i, dot, d]))


# test
ms     = [1.62, 1.63, 1.67, 1.68, 2.1, 2.111, 2.119, 2.138]
ms_res = [1.60, 1.65, 1.65, 1.70, 2.1, 2.100, 2.100, 2.150] # expected rounded values

# result
for m, m_true in zip(ms, ms_res):
    print(m, cround(m), cround(m) == m_true)

Output

1.62 1.6 True
1.63 1.65 True
1.67 1.65 True
1.68 1.7 True
2.1 2.1 True
2.111 2.1 True
2.119 2.1 True
2.138 2.15 True
Answered By: cards
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.