---
# System prepended metadata

title: 'Rounding, Decimal'
tags: [Python]

---

---
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 後面仍有數，則進位 |