This shows the five results with lowest error, obtained using both multiplying by 0.1, dividing by 10, and by using fractions and avoiding the approximations altogether.

From the exact results we can tell that there are four equally wrong candidates all having an error of exactly 5.

The floating point versions also find the same candidates, though with some distortion to error values and/or input values due to using a questionable data type to represent them.

On the flip side, the exact version is much slower. Floats have hardware support, they are *fast*.

```
multiply by 0.1
[res(err=4.999999999999999, m=0.30000000000000004, b=1.7000000000000002),
res(err=5.0, m=0.4, b=1.6),
res(err=5.0, m=0.5, b=1.5),
res(err=5.0, m=0.6000000000000001, b=1.4000000000000001),
res(err=5.1, m=0.4, b=1.5)]
divide by 10
[res(err=5.0, m=0.4, b=1.6),
res(err=5.0, m=0.5, b=1.5),
res(err=5.0, m=0.6, b=1.4),
res(err=5.000000000000001, m=0.3, b=1.7),
res(err=5.1, m=0.3, b=1.6)]
exact math
[res(err=Fraction(5, 1), m=Fraction(3, 10), b=Fraction(17, 10)),
res(err=Fraction(5, 1), m=Fraction(2, 5), b=Fraction(8, 5)),
res(err=Fraction(5, 1), m=Fraction(1, 2), b=Fraction(3, 2)),
res(err=Fraction(5, 1), m=Fraction(3, 5), b=Fraction(7, 5)),
res(err=Fraction(51, 10), m=Fraction(3, 10), b=Fraction(8, 5))]
```

```
from collections import namedtuple
from fractions import Fraction
from functools import partial
from operator import mul, truediv as div
from pprint import pformat
def flip(f):
def flipped(a, b):
return f(b, a)
return flipped
def calculate_all_error(m, b, points):
def error(point):
x, y = point
prediction = m * x + b
return abs(y - prediction)
return sum(map(error, points))
def run(strategy):
return [
res(calculate_all_error(m, b, datapoints), m, b)
for m in range(-100, 101)
for m in [strategy(m)]
for b in range(-200, 201)
for b in [strategy(b)]
]
datapoints = [(1, 2), (2, 0), (3, 4), (4, 4), (5, 3)]
res = namedtuple('res', ['err', 'm', 'b'])
methods = [('multiply by 0.1', partial(mul, 0.1)),
('divide by 10', partial(flip(div), 10)),
('exact math', partial(flip(Fraction), 10))]
list(map(print, (
desc + '\n' + pformat(sorted(run(strat))[:5])
for desc, strat in methods
)))
```