--- tags: Python --- # Rounding, Decimal ## round `round` 在 Python2 和 Python3 的定義不同。 Python2 使用四捨五入: > 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**. > > [name=[`round(number[, ndigits])` / Python2](https://docs.python.org/2.7/library/functions.html#round)] Python3 使用 Bankers rounding 四捨六入五成雙: > 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**. > > [name=[`round(number[, ndigits])` / Python3](https://docs.python.org/3/library/functions.html#round)] 文件上也有提及到,有時會出現預料不到的情形,因為大多數的十進制小數都不能精確地表示為二進制小數: > 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**. ```python >>> Decimal(2.675) Decimal('2.67499999999999982236431605997495353221893310546875') >>> Decimal('2.675') Decimal('2.675') ``` > If you’re in a situation where you care which way your decimal halfway-cases are rounded, you should consider using the decimal module. Incidentally, the decimal module also provides a nice way to “see” the exact value that’s stored in any particular Python float. > > [name=[Floating Point Arithmetic: Issues and Limitations / Python](https://docs.python.org/2.7/tutorial/floatingpoint.html#tut-fp-issues)] ## [Decimal](https://docs.python.org/3/library/decimal.html) Decimal 預設也是採用`ROUND_HALF_EVEN` (四捨六入五成雙),可以透過 rounding 給予 `ROUND_HALF_UP` (四捨五入)調整方式。 ```python from decimal import ( Decimal, ROUND_HALF_UP, ) Decimal('0.645').quantize(Decimal('0.00'), rounding=ROUND_HALF_UP) ``` > [`decimal.ROUND_HALF_EVEN`](https://docs.python.org/3/library/decimal.html#decimal.ROUND_HALF_EVEN): Round to nearest with ties going to nearest even integer. > > [`decimal.ROUND_HALF_UP`](https://docs.python.org/3/library/decimal.html#decimal.ROUND_HALF_UP): Round to nearest with ties going away from zero. ## 四捨六入五成雙 四捨五入會造成整體的數字偏大,而 Banker's Rounding 的方法會讓整體數值偏差更小。 | `num` | `round(num)` | Description | |---------|--------------|-------------| | `5.4` | `5` | 小於 5 捨去 | | `5.6` | `6` | 大於 5 進位 | | `5.5` | `6` | 如果保留位數的後一位如果是 5,而且 5 後面沒有數,則看前一位數,奇進偶捨 | | `6.5` | `6` | | `6.51` | `7` | 如果保留位數的後一位如果是 5,而且 5 後面仍有數,則進位 |