Merge pull request #268 from LiquidFun/master

Add new snippet: banker's rounding
This commit is contained in:
Satwik Kansal 2021-05-11 02:03:45 +05:30 committed by GitHub
commit 897b915f11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 0 deletions

1
CONTRIBUTORS.md vendored
View File

@ -24,6 +24,7 @@ Following are the wonderful people (in no specific order) who have contributed t
| Jongy | [Jongy](https://github.com/Jongy) | [#208](https://github.com/satwikkansal/wtfpython/issues/208), [#210](https://github.com/satwikkansal/wtfpython/issues/210), [#233](https://github.com/satwikkansal/wtfpython/issues/233) |
| Diptangsu Goswami | [diptangsu](https://github.com/diptangsu) | [#193](https://github.com/satwikkansal/wtfpython/issues/193) |
| Charles | [charles-l](https://github.com/charles-l) | [#245](https://github.com/satwikkansal/wtfpython/issues/245)
| LiquidFun | [LiquidFun](https://github.com/LiquidFun) | [#267](https://github.com/satwikkansal/wtfpython/issues/267)
---

53
README.md vendored
View File

@ -70,6 +70,7 @@ So, here we go...
+ [ Catching the Exceptions](#-catching-the-exceptions)
+ [ Same operands, different story!](#-same-operands-different-story)
+ [ Name resolution ignoring class scope](#-name-resolution-ignoring-class-scope)
+ [ Rounding like a banker *](#-rounding-like-a-banker-)
+ [ Needles in a Haystack *](#-needles-in-a-haystack-)
+ [ Splitsies *](#-splitsies-)
+ [ Wild imports *](#-wild-imports-)
@ -2532,6 +2533,58 @@ class SomeClass:
---
### ▶ Rounding like a banker *
Let's implement a naive function to get the middle element of a list:
```py
def get_middle(some_list):
mid_index = round(len(some_list) / 2)
return some_list[mid_index - 1]
```
**Python 3.x:**
```py
>>> get_middle([1]) # looks good
1
>>> get_middle([1,2,3]) # looks good
2
>>> get_middle([1,2,3,4,5]) # huh?
2
>>> len([1,2,3,4,5]) / 2 # good
2.5
>>> round(len([1,2,3,4,5]) / 2) # why?
2
```
It seems as though Python rounded 2.5 to 2.
#### 💡 Explanation:
This is not a float precision error, in fact, this behavior is intentional. Since Python 3.0, `round()` uses [banker's rounding](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even) where .5 fractions are rounded to the nearest **even** number:
```py
>>> round(0.5)
0
>>> round(1.5)
2
>>> round(2.5)
2
>>> import numpy # numpy does the same
>>> numpy.round(0.5)
0.0
>>> numpy.round(1.5)
2.0
>>> numpy.round(2.5)
2.0
```
This is the recommended way to round .5 fractions as described in [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules). However, the other way (round away from zero) is taught in school most of the time, so banker's rounding is likely not that well known. Furthermore, some of the most popular programming languages (for example: JavaScript, Java, C/C++, Ruby, Rust) do not use banker's rounding either. Therefore, this is still quite special to Python and may result in confusion when rounding fractions.
See the [round() docs](https://docs.python.org/3/library/functions.html#round) or [this stackoverflow thread](https://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior) for more information.
Note that `get_middle([1])` only returned 1 because the index was `round(0.5) - 1 = 0 - 1 = -1`, returning the last element in the list.
---
### ▶ Needles in a Haystack *
<!-- Example ID: 52a199b1-989a-4b28-8910-dff562cebba9 --->