I've always wanted to write about this, but because it's a minor point, I've been too lazy to get to it. However, I'd better make up for it now; leaving it alone will eventually be a problem.

The round function is very simple: it rounds a floating-point number to a specified number of decimal places. For example:

>>> round(10.0/3, 2)
3.33
>>> round(20/7)
3

The first parameter is a floating-point number, and the second parameter is the number of decimal places to keep, which is optional. If omitted, it defaults to rounding to an integer.

Such a simple function—how could there be any pitfalls?

1. The result of round depends on the Python version

Let's see what's different in Python 2 and Python 3:

$ python
Python 2.7.8 (default, Jun 18 2015, 18:54:19) 
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> round(0.5)
1.0

$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> round(0.5)
0

Fun, isn't it?

If we read the Python documentation, it says this:

In the Python 2.7 doc, at the end of round(), it says, "Values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done away from 0." The retained value will be kept to the side closer to the previous digit (rounding to the nearest); if it is equally distant from both ends, it will be kept to the side farther from 0. So round(0.5) rounds to 1, and round(-0.5) rounds to -1.

But in the Python 3.5 doc, the documentation has changed to: "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." If it is equally distant from both sides, it will be kept to the even side. For example, round(0.5) and round(-0.5) both round to 0, while round(1.5) rounds to 2.

So if you have a project migrating from Py2 to Py3, be careful with round (of course, also be careful with / and //, print, and some non-mainstream libraries).

>>> round(2.675, 2)
2.67

Both the Python 2 and Python 3 docs give the same example, and the original text says:

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. See Floating Point Arithmetic: Issues and Limitations for more information.

Simply put, the result of round(2.675, 2) should be 2.68 whether we look at Python 2 or 3, but it turns out to be 2.67. Why? This is related to the precision of floating-point numbers. We know that floating-point numbers may not be represented exactly in a machine, because when converted into a string of 1s and 0s, they may have infinite digits, and the machine has already truncated them. So the number 2.675 stored in the machine is slightly smaller than the actual number. This slight difference makes it a bit closer to 2.67, so when keeping two decimal places, it rounds to 2.67.

That's all. Unless you don't have high precision requirements, try to avoid using the round() function. For approximate calculations, we have other options:

  • Use some functions in the math module, such as math.ceiling (ceiling division).
  • Python has built-in integer division: in Python 2 it is /, in Python 3 it is //, and there is also the div function.
  • String formatting can be used for truncation, for example "%.2f" % value (keeps two decimal places and turns it into a string... If you still want a floating-point number, please wrap it in float()).
  • Of course, if you require very high floating-point precision, please use 'dese mo'—no, no, please use the decimal module.

That's it.

Source address: http://www.cnblogs.com/anpengapple/p/6507271.html