2

Rounding on 1 decimal is not working correct:

See below:

round(11.35, 1)
11.3

round(1.35, 1)
1.4

How can this be solved in Python?

The solution of this problem is:

def round_decimal(value, rounding):
    number = decimal.Decimal(str(value))
    decimal_point = float("1e%d" % -rounding)
    return float(number.quantize(decimal.Decimal(str(decimal_point))))
BioGeek
  • 21,897
  • 23
  • 83
  • 145
Robert
  • 305
  • 1
  • 2
  • 14
  • Yes, I have seached on internet. But I cloudn't find a clean way to fix this problem. – Robert Oct 08 '14 at 08:54
  • Are you still stuck? – David Heffernan Oct 08 '14 at 14:03
  • The [documentation](https://docs.python.org/2/library/functions.html#round) already explains the issue and gives a pointer for further reading. See the note that starts "The behavior of round() for floats can be surprising: ...". – Mark Dickinson Oct 09 '14 at 08:56

3 Answers3

5

This is a problem with the representation of decimals in computers in general (so non-specific to Python).

The way I thought this is solved is by using the standard library module decimal. In your case it would look something like this:

num1 = decimal.Decimal("11.35")
print num1.quantize(decimal.Decimal("0.1")) # round to one decimal
# output: 11.4

num2 = decimal.Decimal("1.35")
print num2.quantize(decimal.Decimal("0.1"))
# output: 1.4
Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
3

The reason for this is that 11.35 is held as a float which is stored using binary floating point representation. And 11.35 cannot be represented exactly as a binary floating point value.

Representable binary floating point values have the form s×2e where s and e are integers. Note that 11.35 cannot be written in this form. What happens in Python when you write 11.35 is that the system uses the closest representable value.

The closest double precision value to 11.35 is:

11.35 = + 11.34999 99999 99999 64472 86321 19949 90706 44378 66210 9375

This explains why round(11.35, 1) behaves as it does.

Interestingly, round(11.35, 1) isn't even exactly equal to 11.3 because 11.3 is not exactly representable using binary floating point. And so it goes on.

If you want to represent 11.35 exactly then you will need to store it in a decimal data type. The decimal standard library is the obvious way to do so in Python. This question covers that topic in some detail: How can I format a decimal to always show 2 decimal places?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

In addition to the previous answers, I think it is helpful to know the rules of rounding. You assume that the value 11.35 should be rounded to 11.4, but in reality, rounding down is an option when you hit the mid-point value in rounding. See: http://en.wikipedia.org/wiki/Rounding

Using the decimal library is the best way to solve you issue in python for your case.

code base 5000
  • 3,812
  • 13
  • 44
  • 73