Look at the following Christmas bug Santa has brought…
The problem concerns the builtin function round().
In its current implementation, rounding is done to the nearest float that can be represented by the machine.
This is wrong, rounding should be done to the nearest float with the correct least significant decimal that can be represented by the machine.
Consider the following little main.py script:
Code: Select all
f = 1011.640071
print('\n%f = float' % f)
print('%f = float rounded to one decimal' % round(f, 1))
print('%6.1f = formatted rounded float\n' % round(f, 1))
delta = 0.000040
print('%f = float correctly rounded to least significant first decimal' % (round(f, 1) + delta))
print('%6.1f = formatted correctly rounded float\n' % (round(f, 1) + delta))
epsilon = abs(7./3 - 4./3 - 1)
print('%f = 1000 × machine epsilon' % (1000 * epsilon))
print(epsilon)
print()
Code: Select all
MicroPython v1.9.2-87-gda8c4c26 on 2017-09-13; PYBv1.1 with STM32F405RG
1011.639952 = float
1011.599898 = float rounded to one decimal
1011.5 = formatted rounded float
1011.600017 = float correctly rounded to least significant first decimal
1011.6 = formatted correctly rounded float
0.000119 = 1000 × machine epsilon
1.192093e-07
Code: Select all
MicroPython 2ac6da2 on 2017-12-18; LoPy with ESP32
1011.639952 = float
1011.599898 = float rounded to one decimal
1011.5 = formatted rounded float
1011.600017 = float correctly rounded to least significant first decimal
1011.6 = formatted correctly rounded float
0.000119 = 1000 × machine epsilon
1.192093e-07
For certain applications, such poor rounding can have very serious consequences down the line…
This finding may account for the multitude of other reports complaining about round() behaviour:
- viewtopic.php?t=802
- https://github.com/bbcmicrobit/micropython/issues/367
- https://github.com/micropython/micropython/issues/2616
- https://support.microbit.org/support/so ... ding-error