Pytanie Wydrukuj prawdziwe korzenie tylko w numpy


Mam coś takiego:

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

Oczywiście wynik jest następujący:

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

Jednak za pomocą tej metody, jak mogę uzyskać tylko wydrukować prawdziwe korzenie, jeśli w ogóle (jak pływaki)? Znaczenie właśnie dla mojego przykładu:

0.57030329

10
2018-01-22 04:21


pochodzenie


Naprawdę tego nie potrzebuję, ponieważ ma część wyobrażoną, ze wszystkich równań, które uruchomi mój skrypt, przynajmniej jeden root będzie prawdziwy, i tego właśnie potrzebuję :) - rodrigocf


Odpowiedzi:


Możesz to zrobić, używając iscomplex następująco:

r = numpy.roots(coefs)

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

Możesz również użyć jest realne jak wskazano w komentarzach:

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

3
2018-01-22 04:32



jakikolwiek powód by użyć negacji iscomplex zamiast isreal? - M4rtini
@ M4rtini Tylko moje szczęście. Ale oczywiście, isreal byłoby bardziej czytelne :-) - Marcin
Prawdopodobnie nieco szybciej nie trzeba odwracać matrycy boolowskiej :) - M4rtini
@ M4rtini Yep. Dodałem, że jest prawdziwe w odpowiedzi. - Marcin
@Marcin, zauważ, że to nie jest poprawna odpowiedź. - gg349


Nie używaj .iscomplex() lub .isreal(), bo roots() jest algorytmem numerycznym i zwraca numeryczne przybliżenie rzeczywistych źródeł wielomianu. Może to prowadzić do fałszywych urojonych części, które są interpretowane przez powyższe metody jako rozwiązania.

Przykład:

# 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]

Zamiast tego użyj pewnego progu w zależności od twojego problemu. Ponadto, ponieważ interesują Cię prawdziwe korzenie, zachowaj tylko prawdziwą część:

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

20
2018-01-22 08:33



+1 - Wiele osób zapomina, że ​​niedokładność liczbowa może prowadzić do niewielkich wyimaginowanych współczynników i niezależnie od tego, jak małe są, liczby będą nadal klasyfikowane jako wyobrażeniowe. - rayryeng


Mam nadzieję, że ta pomoc.

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

0
2018-01-21 20:06