RuntimeWarning: Ungültiger Wert beim Teilen

92

Ich muss ein Programm nach Eulers Methode für das Modell "Ball in a Spring" erstellen

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()

Ich bekomme immer wieder diesen Fehler:

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

Ich kann es nicht herausfinden, was ist mit dem Code falsch?

Bogdan Osyka
quelle
Drucken Sie aus, was in jedem der kleineren Elemente in dieser Codezeile vor sich geht. Nur so kann es debuggt werden.
CppLearner
2
Sie haben nans für rr, was diesen Fehler auslöst. Das Problem mit rrist das, von r[i,:]dem in einigen Fällen gleich ist array([ nan, nan]). Wie bei @CppLearner erwähnt, besteht der beste Weg zum Debuggen (oder Schreiben) von Code darin, jeden kleineren Teil vor der Implementierung zu testen.
Kosmose

Antworten:

153

Ich denke, Ihr Code versucht, "durch Null zu teilen" oder "durch NaN zu teilen". Wenn Sie sich dessen bewusst sind und nicht möchten, dass es Sie stört, können Sie Folgendes versuchen:

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

Weitere Details finden Sie unter:

Yan Zhu
quelle
70
Dies kann nützlich sein, with NP.errstate(divide='ignore',invalid='ignore'):wenn Sie die Warnungen für einen Codeblock unterdrücken möchten.
GWW
8
Warum sollte man eine Division durch Null oder NaN ignorieren wollen?
x Quadrat
7
@xsquared Wenn Sie den Wert nach der Teilung selbst korrekt verarbeitet haben und Ihren Code an Benutzer verteilen (oder es leid sind, die Warnung zu sehen). with np.errstate(...)Damit können Sie dies sicher nur für den behandelten Fall tun.
reve_etrange
2
@reve_etrange Dass ich es viel akzeptabler finde, als Divisionen durch Null generell zu ignorieren.
x Quadrat
1
Es ist besser, dies vor der Zeile zu setzen, die den Fehler verursacht, und dann nach der Zeile 'warn'durch den Befehl auf den normalen Zustand zurückzusetzennp.seterr(divide='warn', invalid='warn')
Mohammad ElNesr
15

Die Python-Indizierung beginnt bei 0 (anstatt bei 1), daher definiert Ihre Zuweisung "r [1,:] = r0" das zweite (dh Index 1) Element von r und belässt das erste (Index 0) Element als Paar von Nullen. Der erste Wert von i in Ihrer for-Schleife ist 0, also erhält rr die Quadratwurzel des Punktprodukts des ersten Eintrags in r mit sich selbst (was 0 ist), und die Division durch rr in der nachfolgenden Zeile löst den Fehler aus.

Kinch
quelle
9

Um eine Division durch Null zu verhindern, können Sie die Ausgabe 'out' vorinitialisieren, wenn der Fehler div0 auftritt, z. B. np.wherenicht abschneiden, da die gesamte Zeile unabhängig von der Bedingung ausgewertet wird.

Beispiel mit Vorinitialisierung:

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
qrtLs
quelle
4

Sie teilen, durch rrdie 0.0 sein kann. Überprüfen Sie, ob rrNull ist, und tun Sie etwas Vernünftiges, als es im Nenner zu verwenden.

Crayzeewulf
quelle