You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+53
Original file line number
Diff line number
Diff line change
@@ -70,6 +70,7 @@ So, here we go...
70
70
+[▶ Catching the Exceptions](#-catching-the-exceptions)
71
71
+[▶ Same operands, different story!](#-same-operands-different-story)
72
72
+[▶ Name resolution ignoring class scope](#-name-resolution-ignoring-class-scope)
73
+
+[▶ Rounding like a banker *](#-rounding-like-a-banker-)
73
74
+[▶ Needles in a Haystack *](#-needles-in-a-haystack-)
74
75
+[▶ Splitsies *](#-splitsies-)
75
76
+[▶ Wild imports *](#-wild-imports-)
@@ -2532,6 +2533,58 @@ class SomeClass:
2532
2533
2533
2534
---
2534
2535
2536
+
### ▶ Rounding like a banker *
2537
+
2538
+
Let's implement a naive function to get the middle element of a list:
2539
+
```py
2540
+
def get_middle(some_list):
2541
+
mid_index = round(len(some_list) / 2)
2542
+
return some_list[mid_index - 1]
2543
+
```
2544
+
2545
+
**Python 3.x:**
2546
+
```py
2547
+
>>> get_middle([1]) # looks good
2548
+
1
2549
+
>>> get_middle([1,2,3]) # looks good
2550
+
2
2551
+
>>> get_middle([1,2,3,4,5]) # huh?
2552
+
2
2553
+
>>> len([1,2,3,4,5]) / 2 # good
2554
+
2.5
2555
+
>>> round(len([1,2,3,4,5]) / 2) # why?
2556
+
2
2557
+
```
2558
+
It seems as though Python rounded 2.5 to 2.
2559
+
2560
+
#### 💡 Explanation:
2561
+
2562
+
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:
2563
+
2564
+
```py
2565
+
>>> round(0.5)
2566
+
0
2567
+
>>> round(1.5)
2568
+
2
2569
+
>>> round(2.5)
2570
+
2
2571
+
>>> import numpy # numpy does the same
2572
+
>>> numpy.round(0.5)
2573
+
0.0
2574
+
>>> numpy.round(1.5)
2575
+
2.0
2576
+
>>> numpy.round(2.5)
2577
+
2.0
2578
+
```
2579
+
2580
+
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.
2581
+
2582
+
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.
2583
+
2584
+
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.
2585
+
2586
+
---
2587
+
2535
2588
### ▶ Needles in a Haystack *
2536
2589
2537
2590
<!-- Example ID: 52a199b1-989a-4b28-8910-dff562cebba9 --->
0 commit comments