source: http://calculuswithjulia.github.io/precalc/polynomial_roots.html

Roots of a polynomial

using CalculusWithJulia  # to load Plots and SymPy
f(x)=x^2 - x
## f (generic function with 1 method)
plot(f, -2, 2)

plot!(zero)

The factor theorem relates the roots of a polynomial with its factors: \(r\) is a root of \(p\) if and only if \((x-r)\) is a factor of the polynomial \(p\).

Polynomial Division

@vars x real=true
## (x,)
(x^4 + 2x^2 + 5) / (x-2)
##  4      2    
## x  + 2*x  + 5
## -------------
##     x - 2
q, r=divrem(x^4 + 2x^2 + 5, x-2)
## (floor((x^4 + 2*x^2 + 5)/(x - 2)), x^4 + 2*x^2 - (x - 2)*floor((x^4 + 2*x^2 + 5)/(x - 2)) + 5)
apart((x^4 + 2x^2+5)/(x-2))
##  3      2                29 
## x  + 2*x  + 6*x + 12 + -----
##                        x - 2
p = 2x^4 + x^3 - 19x^2 - 9x + 9
##    4    3       2          
## 2*x  + x  - 19*x  - 9*x + 9
factor(p)
## (x - 3)*(x + 1)*(x + 3)*(2*x - 1)

Fundamental theorem of algebra

A polynomial of degree \(n\) has at most \(n\) real roots.

plot(x^2 - 1, -2, 2, legend=false)

plot!(x^2)

plot!(x^2 + 1)

plot!(zero)

solve(x^2 + 2x -3)
## 2-element Array{Sym,1}:
##  -3
##   1
@vars a b c
## (a, b, c)
solve(a*x^2 + b*x + c, x)
## 2-element Array{Sym,1}:
##  (-b + sqrt(-4*a*c + b^2))/(2*a)
##  -(b + sqrt(-4*a*c + b^2))/(2*a)
@vars a
## (a,)
@vars b real=true
## (b,)
c=symbols("c", positive=true)
## c
solve(a^2 + 1)  # works, as a can be complex
## 2-element Array{Sym,1}:
##  -I
##   I
solve(b^2 + 1) # fails, as b is assumed real
## 0-element Array{Any,1}
solve(c+1)  # fails, as c is assumed positive
## 0-element Array{Any,1}
p = x^2 - 2
##  2    
## x  - 2
factor(p)
##  2    
## x  - 2
rts = solve(p)
## 2-element Array{Sym,1}:
##  -sqrt(2)
##   sqrt(2)
prod(x-r for r in rts)
## /      ___\ /      ___\
## \x - \/ 2 /*\x + \/ 2 /
@vars x
## (x,)
solve(x^4 - 2x -1)
## 4-element Array{Sym,1}:
##  -sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3))/2 - sqrt(-4/sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3)) - 2*(1/4 + sqrt(129)/36)^(1/3) + 2/(3*(1/4 + sqrt(129)/36)^(1/3)))/2
##  -sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3))/2 + sqrt(-4/sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3)) - 2*(1/4 + sqrt(129)/36)^(1/3) + 2/(3*(1/4 + sqrt(129)/36)^(1/3)))/2
##   sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3))/2 + sqrt(-2*(1/4 + sqrt(129)/36)^(1/3) + 2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 4/sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3)))/2
##  -sqrt(-2*(1/4 + sqrt(129)/36)^(1/3) + 2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 4/sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3)))/2 + sqrt(-2/(3*(1/4 + sqrt(129)/36)^(1/3)) + 2*(1/4 + sqrt(129)/36)^(1/3))/2
solve(x^5 - x + 1)
## 5-element Array{Sym,1}:
##  CRootOf(x^5 - x + 1, 0)
##  CRootOf(x^5 - x + 1, 1)
##  CRootOf(x^5 - x + 1, 2)
##  CRootOf(x^5 - x + 1, 3)
##  CRootOf(x^5 - x + 1, 4)

Numerically finding roots

rts = solve(x^5 - x + 1)
## 5-element Array{Sym,1}:
##  CRootOf(x^5 - x + 1, 0)
##  CRootOf(x^5 - x + 1, 1)
##  CRootOf(x^5 - x + 1, 2)
##  CRootOf(x^5 - x + 1, 3)
##  CRootOf(x^5 - x + 1, 4)
N.(rts)
## 5-element Array{Number,1}:
##                      -1.167303978261418684256045899854842180720560371525489039140082449275651903429536
##  -0.18123244446987538 - 1.0839541013177107im                                                          
##  -0.18123244446987538 + 1.0839541013177107im                                                          
##    0.7648844336005847 - 0.35247154603172626im                                                         
##    0.7648844336005847 + 0.35247154603172626im
ex = x^7 -3x^6 +  2x^5 -1x^3 +  2x^2 + 1x^1  - 2
##  7      6      5    3      2        
## x  - 3*x  + 2*x  - x  + 2*x  + x - 2
solve(ex)
## 7-element Array{Sym,1}:
##                        1
##                        2
##  CRootOf(x^5 - x - 1, 0)
##  CRootOf(x^5 - x - 1, 1)
##  CRootOf(x^5 - x - 1, 2)
##  CRootOf(x^5 - x - 1, 3)
##  CRootOf(x^5 - x - 1, 4)
N.(solve(ex))
## 7-element Array{Number,1}:
##                      1                                                                               
##                      2                                                                               
##                      1.167303978261418684256045899854842180720560371525489039140082449275651903429536
##  -0.7648844336005847 - 0.35247154603172626im                                                         
##  -0.7648844336005847 + 0.35247154603172626im                                                         
##  0.18123244446987538 - 1.0839541013177107im                                                          
##  0.18123244446987538 + 1.0839541013177107im

The solveset function

p = 8x^4 - 8x^2 + 1
##    4      2    
## 8*x  - 8*x  + 1
rts = solveset(p)
##        ___________       ___________        ___________       ___________ 
##       /       ___       /       ___        /   ___           /   ___      
##      /  1   \/ 2       /  1   \/ 2        /  \/ 2    1      /  \/ 2    1  
## {-  /   - - ----- ,   /   - - ----- , -  /   ----- + - ,   /   ----- + - }
##   \/    2     4     \/    2     4      \/      4     2   \/      4     2
elements(rts)
## 4-element Array{Sym,1}:
##  -sqrt(1/2 - sqrt(2)/4)
##  -sqrt(sqrt(2)/4 + 1/2)
##   sqrt(sqrt(2)/4 + 1/2)
##   sqrt(1/2 - sqrt(2)/4)
N.(elements(solveset(p)))
## 4-element Array{BigFloat,1}:
##  -0.3826834323650897717284599840303988667613445624856270414338006356275460339600903
##  -0.9238795325112867561281831893967882868224166258636424861150977312805350075011054
##   0.9238795325112867561281831893967882868224166258636424861150977312805350075011054
##   0.3826834323650897717284599840303988667613445624856270414338006356275460339600903

Do numeric methods matter when you can just graph?

p = x^5 - 100x^4 + 4000x^3 - 80000x^2 + 799999x - 3199979
##  5        4         3          2                     
## x  - 100*x  + 4000*x  - 80000*x  + 799999*x - 3199979
plot(p, -10, 10)

plot(p, 10, 20)

plot(p, 18, 22)