Round to the nearest float with the correct least significant decimal.

You have all been very naughty!
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: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()
Here is the output on a PyBoard:
MicroPython v1.9.287gda8c4c26 on 20170913; 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.192093e07
Things are not any different on a Pycom LoPy ESP32:
MicroPython 2ac6da2 on 20171218; 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.192093e07
Note that the difference between correct and erroneous rounding is about a 1000 times the machine epsilon, which makes sense.
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: https://forum.micropython.org/viewtopic.php?t=802
 https://github.com/bbcmicrobit/micropython/issues/367
 https://github.com/micropython/micropython/issues/2616
 https://support.microbit.org/support/solutions/articles/19000026098strangeroundingerror
I also reported this bug here: