RuntimeWarning: valore non valido rilevato in divide


96

Devo creare un programma usando il metodo di Eulero per il modello "palla in una molla"

from pylab import*
from math import*
m=0.1
Lo=1
tt=30
k=200
t=20
g=9.81
dt=0.01
n=int((ceil(t/dt)))
km=k/m
r0=[-5,5*sqrt(3)]
v0=[-5,5*sqrt(3)]
a=zeros((n,2))
r=zeros((n,2))
v=zeros((n,2))
t=zeros((n,2))
r[1,:]=r0
v[1,:]=v0
for i in range(n-1):
    rr=dot(r[i,:],r[i,:])**0.5
    a=-g+km*cos(tt)*(rr-L0)*r[i,:]/rr
    v[i+1,:]=v[i,:]+a*dt
    r[i+1,:]=r[i,:]+v[i+1,:]*dt
    t[i+1]=t[i]+dt

    #print norm(r[i,:])

plot(r[:,0],r[:,1])
xlim(-100,100)
ylim(-100,100)
xlabel('x [m]')
ylabel('y [m]')

show()

Continuo a ricevere questo errore:

a=-g+km*cos(tt)*(rr-L0)*r[i,:]/rr
RuntimeWarning: invalid value encountered in divide

Non riesco a capirlo, cosa c'è di sbagliato nel codice?


stampare cosa sta succedendo in ciascuno degli elementi più piccoli in quella riga di codice. Questo è l'unico modo per eseguire il debug.
CppLearner

2
Hai nans per rr, che sta lanciando quell'errore. Il problema con rrè derivante da r[i,:]cui è uguale, in alcuni casi, a array([ nan, nan]). Come menzionato da @CppLearner, il modo migliore per eseguire il debug (o scrivere) del codice è testare ogni porzione più piccola prima dell'implementazione.
cosmosis

Risposte:


160

Penso che il tuo codice stia cercando di "dividere per zero" o "dividere per NaN". Se ne sei consapevole e non vuoi che ti disturbi, puoi provare:

import numpy as np
np.seterr(divide='ignore', invalid='ignore')

Per maggiori dettagli vedere:


76
Può essere utile da utilizzare with NP.errstate(divide='ignore',invalid='ignore'):se si desidera sopprimere gli avvisi per un blocco di codice.
GWW

8
Perché si dovrebbe voler ignorare una divisione per zero o NaN?
x al quadrato il

7
@xsquared Quando hai gestito correttamente il valore da solo, dopo la divisione, e stai distribuendo il tuo codice agli utenti (o sei stanco di vedere l'avvertimento). with np.errstate(...)ti consente di farlo in sicurezza solo per il caso gestito.
reve_etrange

2
@reve_etrange Che trovo molto più accettabile che ignorare generalmente le divisioni per zero.
x al quadrato

1
è meglio impostarlo prima della riga che causa l'errore, quindi resettare dopo la riga allo stato normale del 'warn'comandonp.seterr(divide='warn', invalid='warn')
Mohammad ElNesr

15

L'indicizzazione di Python inizia da 0 (anziché da 1), quindi l'assegnazione "r [1 ,:] = r0" definisce il secondo elemento (cioè indice 1) di r e lascia il primo elemento (indice 0) come una coppia di zeri. Il primo valore di i nel tuo ciclo for è 0, quindi rr ottiene la radice quadrata del prodotto scalare della prima voce in r con se stesso (che è 0), e la divisione per rr nella riga successiva genera l'errore.


10

Per evitare la divisione per zero è possibile pre-inizializzare l'output 'out' dove si verifica l'errore div0, ad esempio np.wherenon lo taglia poiché la riga completa viene valutata indipendentemente dalla condizione.

esempio con pre-inizializzazione:

a = np.arange(10).reshape(2,5)
a[1,3] = 0
print(a)    #[[0 1 2 3 4], [5 6 7 0 9]]
a[0]/a[1]   # errors at 3/0
out = np.ones( (5) )  #preinit
np.divide(a[0],a[1], out=out, where=a[1]!=0) #only divide nonzeros else 1

4

Stai dividendo per rrche può essere 0,0. Controlla se rrè zero e fai qualcosa di ragionevole oltre a usarlo al denominatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.