Polynomial roots are determined using following code. Roots are displayed with imaginary numbers, but it is actually whole numbers. The 5's should be with out any imaginary value
[5.+1.27882372e-07j 5.-1.27882372e-07j 2.+0.00000000e+00j]
import numpy as np
poly=[1,-10,25] # (x-5)**2
p1 = np.poly1d(poly)
p2 = np.poly1d([1,-2]) # (x-2)
poly2 = p1*p2 # (x-5)**2 * (x-2)
print(poly2.roots)
print(poly2(5))
print(poly2(2))
Solution: Use np.real_if_close(poly2.roots, tol=1e-5) to ignore insgnificant imaginary part.
#remove insignificant imaginary part
formatted_roots = np.real_if_close(poly2.roots, tol=1e-5)
# change back to number format
roots = formatted_roots.astype(float)
Polynomial roots are determined using following code. Roots are displayed with imaginary numbers, but it is actually whole numbers. The 5's should be with out any imaginary value
[5.+1.27882372e-07j 5.-1.27882372e-07j 2.+0.00000000e+00j]
import numpy as np
poly=[1,-10,25] # (x-5)**2
p1 = np.poly1d(poly)
p2 = np.poly1d([1,-2]) # (x-2)
poly2 = p1*p2 # (x-5)**2 * (x-2)
print(poly2.roots)
print(poly2(5))
print(poly2(2))
Solution: Use np.real_if_close(poly2.roots, tol=1e-5) to ignore insgnificant imaginary part.
#remove insignificant imaginary part
formatted_roots = np.real_if_close(poly2.roots, tol=1e-5)
# change back to number format
roots = formatted_roots.astype(float)
Share
Improve this question
edited Nov 19, 2024 at 17:57
cobp
asked Nov 19, 2024 at 16:52
cobpcobp
7721 gold badge6 silver badges20 bronze badges
3
- On my numpy version 1.24.3, I get [5.00000011 4.99999989 2. ] as the result. But you can also look at np.real_if_close() to 'fix' the problem for now. No clue why it is happening though. – Divyansh Gupta Commented Nov 19, 2024 at 16:56
- Numerical calculations are imprecise. You can easily write code such that if the imaginary part is smaller than some threshold of your choosing (either absolute or relative to the real part, then you remove it.) – Frank Yellin Commented Nov 19, 2024 at 17:00
- According to the documentation the floating-point error can be somewhat larger for repeated roots (as here). Presumably this is related to the fact that the slope is zero at the zero of the polynomial. – lastchance Commented Nov 19, 2024 at 17:20
1 Answer
Reset to default 3The small imaginary parts in your results, like 1.27882372e-07j
, happen because of floating-point math errors. These are pretty much just artifacts and not real parts. You can use np.isclose
to verify if these trivial parts are effectively zero and format the output.
This code may work.
import numpy as np
poly = [1, -10, 25] # (x-5)**2
p1 = np.poly1d(poly)
p2 = np.poly1d([1, -2]) # (x-2)
poly2 = p1 * p2 # (x-5)**2 * (x-2)
roots = poly2.roots
# Format roots to show only real parts if imaginary parts are close to zero
formatted_roots = [np.real_if_close(root, tol=1e-5) for root in roots]
print("Roots:", formatted_roots)
print("poly2(5):", poly2(5)) # Evaluate at x=5
print("poly2(2):", poly2(2)) # Evaluate at x=2