2015-01-22 18 views
8

ho qualcosa di simile:stampa radici reali solo in NumPy

coefs = [28, -36, 50, -22] 
print(numpy.roots(coefs)) 

Naturalmente il risultato è:

[ 0.35770550+1.11792657j 0.35770550-1.11792657j 0.57030329+0.j ] 

Tuttavia, utilizzando questo metodo, come faccio a farlo solo per la stampa le radici reali se presenti (come galleggianti)? Significato solo questo per il mio esempio:

0.57030329 
+0

non ho davvero bisogno dal momento che ha una parte immaginaria, di tutte le equazioni mio script verrà eseguito, almeno una radice sarà reale, e questo è quello che ho bisogno :) – rodrigocf

risposta

2

si può fare, usando iscomplex come segue:

r = numpy.roots(coefs) 

In [15]: r[~numpy.iscomplex(r)] 
Out[15]: array([ 0.57030329+0.j]) 

Inoltre è possibile utilizzare isreal come sottolineato nei commenti:

In [17]: r[numpy.isreal(r)] 
Out[17]: array([ 0.57030329+0.j]) 
+1

alcun motivo per usa la negazione di iscomplex invece di isreal? – M4rtini

+0

@ M4rtini Solo la mia felicità. Ma ovviamente, isreal sarebbe più leggibile :-) – Marcin

+1

Probabilmente leggermente più veloce non dover invertire anche la matrice booleana :) – M4rtini

17

Do NON utilizzare .iscomplex() o .isreal(), perché roots() è un algoritmo numerico e restituisce l'approssimazione numerica dell'effettiva radici del polinomio. Questo può portare a parti immaginarie spurie, che sono interpretate dai metodi di cui sopra come soluzioni.

Esempio:

# create a polynomial with these real-valued roots: 
p = numpy.poly([2,3,4,5,56,6,5,4,2,3,8,0,10]) 
# calculate the roots from the polynomial: 
r = numpy.roots(p) 
print(r) # real-valued roots, with spurious imaginary part 
array([ 56.00000000 +0.00000000e+00j, 10.00000000 +0.00000000e+00j, 
     8.00000000 +0.00000000e+00j, 6.00000000 +0.00000000e+00j, 
     5.00009796 +0.00000000e+00j, 4.99990203 +0.00000000e+00j, 
     4.00008066 +0.00000000e+00j, 3.99991935 +0.00000000e+00j, 
     3.00000598 +0.00000000e+00j, 2.99999403 +0.00000000e+00j, 
     2.00000000 +3.77612207e-06j, 2.00000000 -3.77612207e-06j, 
     0.00000000 +0.00000000e+00j]) 
# using isreal() fails: many correct solutions are discarded 
print(r[numpy.isreal(r)]) 
[ 56.00000000+0.j 10.00000000+0.j 8.00000000+0.j 6.00000000+0.j 
    5.00009796+0.j 4.99990203+0.j 4.00008066+0.j 3.99991935+0.j 
    3.00000598+0.j 2.99999403+0.j 0.00000000+0.j] 

utilizzare alcuni soglia a seconda del vostro problema a portata di mano, invece. Inoltre, dal momento che ti interessano le vere radici, mantieni solo la parte reale:

real_valued = r.real[abs(r.imag)<1e-5] # where I chose 1-e5 as a threshold 
print(real_valued) 
+2

+1 - Un sacco di persone dimenticano che l'imprecisione numerica può portare a coefficienti immaginari insignificanti e non importa quanto piccoli siano, i numeri sarebbero comunque classificati come immaginari. – rayryeng

0

Spero che questo aiuto.

roots = np.roots(coeff); 
for i in range(len(roots)): 
    if np.isreal(roots[i]): 
     print(np.real(roots[i]))