1

I was trying to round UP a decimal with the code I found below, but it doesn't seem to work properly in python(django). Here is the code:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier

Here are some of the results I get when I run the function:

print(round_up(20.232, 2))
print(round_up(20.211, 2))
print(round_up(20.4, 2))

20.24
20.22
20.4

However, for some reason, I get a weird value when I input 80.4. I am getting 80.41 instead of 80.4:

print(round_up(80.4, 2))
80.41

Is there any other way I can round up decimals in python(django)? I have gotten this off the internet, so there might be some other problems other than the one I mentioned above(inputting 80.4). Basically, I just want to round up a decimal to the second decimal point like above(but of course rounding up 80.4 or 20.3 would just be 80.4 and 20.3 respectively). Thank you, and please leave any questions you have.

coderDcoder
  • 585
  • 3
  • 16
  • Does this answer your question? [How to round to 2 decimals with Python?](https://stackoverflow.com/questions/20457038/how-to-round-to-2-decimals-with-python) – itprorh66 Dec 27 '21 at 15:43
  • Not exactly. The link is for round(). I am trying to round UP. – coderDcoder Dec 27 '21 at 15:44
  • 1
    Your problem comes from a floating point error. Try print(80.4 * (10 ** 2)) and see by yourself why this is not working. – Daniel P Dec 27 '21 at 15:47
  • @DanielP Could you please write the code in the format print(round_up(decimal, number))? If possible, I would appreciate it if you can write the full functioning code. – coderDcoder Dec 27 '21 at 15:50

2 Answers2

5

The problem occurs when you multiply float numbers

>>> 80.4 * 100
8040.000000000001

So, math.ceil(80.4 * 100) == 8041

If you wanna be precise, you could use Decimal

from decimal import Decimal, ROUND_CEILING

def round_up_decimal(n, decimals=0):
    multiplier = Decimal(10 ** decimals)
    return (n * multiplier).to_integral(rounding=ROUND_CEILING) / multiplier

print(round_up_decimal(Decimal("20.232"), 2))
print(round_up_decimal(Decimal("20.0"), 2))
print(round_up_decimal(Decimal("20.4"), 2))

print(round_up_decimal(Decimal("80.4"), 2))

Output

20.24
20
20.4
80.4

Also, you can create another function to work with float

def round_up_float(n, decimals=0):
    return float(round_up_decimal(Decimal(str(n)), decimals)) # uses previous function


print(round_up_float(20.232, 2))
print(round_up_float(20.0, 2))
print(round_up_float(20.4, 2))

print(round_up_float(80.4, 2))

Output

20.24
20.0
20.4
80.4
Yevhen Bondar
  • 4,357
  • 1
  • 11
  • 31
  • Thank you for your clear answer. However, may I ask the difference between a decimal and a float? Which one should I be using? – coderDcoder Dec 27 '21 at 16:10
  • 1
    @codebuilder decimal stores your number 'as is', respecting all digits. float instead can slightly change your numbers as you get at `80.4 * 100 == 8040.000000000001`. Decimals are a little bit slower and require more complex syntax than float. So, If you store money or something precise-needed I think you should use Decimals. If you store distance or volume you can use float. But be aware of rounding errors like you've got. – Yevhen Bondar Dec 27 '21 at 16:20
1

I may have misunderstood your question, but as far as I understand, I wanted to write it in case it helps.


Have you tried the round() function already available in Python?

round(20.232, 2)
round(20.0, 2)
round(20.4, 2)
round(80.4, 2)

20.23
20.0
20.4
80.4

I say it again, I answered as far as I understand, of course, this is a ready-made function and it may not be what you want, but if it helps, I would be glad.

Yağız
  • 61
  • 4