3

Sorry, but I really don't know what's the meaning of the defination of round in python 3.3.2 doc:

round(number[, ndigits])
Return the floating point value number rounded to ndigits digits after the decimal point. If ndigits is omitted, it defaults to zero. Delegates to number.__round__(ndigits).

For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2). The return value is an integer if called with one argument, otherwise of the same type as number.

I don't know how come the multiple of 10 and pow.

After reading the following examples, I think round(number,n) works like:

if let number be 123.456, let n be 2

  1. round will get two number:123.45 and 123.46

  2. round compares abs(number-123.45) (0.006) and abs(number-123.46) (0.004),and chooses the smaller one.

  3. so, 123.46 is the result.

and if let number be 123.455, let n be 2:

  1. round will get two number:123.45 and 123.46

  2. round compares abs(number-123.45) (0.005) and abs(number-123.46) (0.005). They are equal. So round checks the last digit of 123.45 and 123.46. The even one is the result.

  3. so, the result is 123.46

Am I right?

If not, could you offer a understandable version of values are rounded to the closest multiple of 10 to the power minus ndigits?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
tcpiper
  • 2,456
  • 2
  • 28
  • 41

2 Answers2

2
ndigits = 0 => pow(10, -ndigits) = 10^(-ndigits) = 1
ndigits = 1 => pow(10, -ndigits) = 10^(-ndigits) = 0.1
etc.

>>> for ndigits in range(6):
...     print round(123.456789, ndigits) / pow(10, -ndigits)
123.0
1235.0
12346.0
123457.0
1234568.0
12345679.0

Basically, the number you get is always an integer multiple of 10^(-ndigits). For ndigits=0, that means the number you get is itself an integer, for ndigits=1 it means it won't have more than one non-zero value after the decimal point.

Vlad
  • 18,195
  • 4
  • 41
  • 71
  • thanks. Now I know the `multiple` must be an integer. and `10 to the power minus ndigits` means pow(10, -ndigits). – tcpiper Nov 18 '13 at 16:03
  • round(2.5) you will have 2 options 3.0 or 2.0 , rounding is done toward the even choice , that's why we get 2.0 , – christianbueno.1 Sep 26 '19 at 04:25
2

It helps to know that anything to the power of 0 equals 1. As ndigits increases, the function:

f(ndigits) = 10-ndigits gets smaller as you increase ndigits. Specifically as you increase ndigits by 1, you simply shift the decimal place of precision one left. e.g. 10^-0 = 1, 10^-1 = .1 and 10^-2 = .01. The place where the 1 is in the answer is the last point of precision for round.

For the part where it says

For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2).

This has unexpected behavior in Python 3 and it will not work for all floats. Consider the example you gave, round(123.455, 2) yields the value 123.45. This is not expected behavior because the closest even multiple of 10^-2 is 123.46, not 123.45!

To understand this, you have to pay special attention to the note below this:

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.

And that is why certain floats will round to the "wrong value" and there is really no easy workaround as far as I am aware. (sadface) You could use fractions (i.e. two variables representing the numerator and the denominator) to represent floats in a custom round function if you want to get different behavior than the unpredictable behavior for floats.

Shashank
  • 13,713
  • 5
  • 37
  • 63