I would like to figure out the roots of the polynomial x^2 - 800x + 160000
, which has a multiple root of 400.
In Matlab, if I type roots([1 -800 160000)
, I correctly get ans = 400.0000, 400.0000
whereas numpy np.roots([1, -800, 160000])
gives me array([400.+2.69940682e-06j, 400.-2.69940682e-06j])
.
Why does numpy show some sort of floating point precision issue when matlab does not? Do they not both use an algorithm based on the companion matrix? How can I reliably determine, in Python, that the "actual" roots are 400, as Matlab seems to be doing?
Edit: This is a "toy" example that I am facing in a larger, more complex algorithm that is not necessarily faced with only real roots and multiple roots i.e. I do not actually know in advance, in my more complicated case, that the root is multiple and real.
I run this slightly ugly test:
max([
np.abs(
(np.roots(
[1, -2 * i, i ** 2]
) / i - 1)
).max()
for i in range(1, 1000000, 10)
])
and got result 1.91e-08
You can do the same for your version of numpy and estimate the precision of answers, and if a ratio of the imaginary part to the real is less than it you can just drop it.
Also, interesting fact from tests: if roots are different, errors are very little, ~1e-16 or even 0, but when roots are the same, errors are almost never zero and have magnitude of 1e-8~1e-9.