RuntimeWarning: bölmede geçersiz değerle karşılaşıldı


96

"Yaydaki top" modeli için Euler'in yöntemini kullanarak bir program yapmam gerekiyor

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

Şu hatayı alıyorum:

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

Çözemiyorum, kodda sorun ne?


o kod satırındaki daha küçük öğelerin her birinde neler olup bittiğini yazdırın. Hata ayıklamanın tek yolu bu.
CppLearner

2
You have naniçin s rrhatayı atıyor. rrİle ilgili sorun r[i,:], bazı durumlarda eşit olan şeyden kaynaklanıyor array([ nan, nan]). @CppLearner'ın da belirttiği gibi, kodda hata ayıklamanın (veya yazmanın) en iyi yolu, uygulamadan önce her küçük bölümü test etmektir.
cosmosis

Yanıtlar:


161

Sanırım kodunuz "sıfıra bölmeye" veya "NaN ile bölmeye" çalışıyor. Bunun farkındaysanız ve sizi rahatsız etmesini istemiyorsanız, deneyebilirsiniz:

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

Daha fazla ayrıntı için bkz .:


76
Bir with NP.errstate(divide='ignore',invalid='ignore'):kod bloğu için uyarıları bastırmak istiyorsanız kullanmak faydalı olabilir .
GWW

8
Sıfır veya NaN ile bölme neden göz ardı edilir?
x kare

7
@xsquared Değeri kendiniz doğru bir şekilde ele aldığınızda, bölmeden sonra kodunuzu kullanıcılara dağıtıyorsanız (veya uyarıyı görmekten yoruluyorsanız). with np.errstate(...)sadece ele alınan durum için bunu güvenli bir şekilde yapmanızı sağlar.
reve_etrange

2
@reve_etrange Genelde sıfıra bölmeyi görmezden gelmekten çok daha kabul edilebilir buluyorum.
x kare

1
Bunu hataya neden olan satırdan önce ayarlamak ve ardından satırdan sonra'warn' komutla normal durumuna sıfırlamak daha np.seterr(divide='warn', invalid='warn')
iyidir

15

Python indeksleme 0'da başlar (1 yerine), bu nedenle "r [1 ,:] = r0" atamanız , r'nin ikinci (yani indeks 1) öğesini tanımlar ve ilk (indeks 0) elementi bir çift sıfır olarak bırakır. For döngünüzdeki i'nin ilk değeri 0'dır, bu nedenle rr, r'deki ilk girdinin iç çarpımının karekökünü alır (0'dır) ve sonraki satırdaki rr'ye bölme hatayı atar.


10

Sıfıra bölünmeyi önlemek için, div0 hatasının meydana geldiği yerde çıktı 'çıkışını' önceden başlatabilirsiniz, örneğin, koşuldan np.wherebağımsız olarak tüm hat değerlendirildiği için onu kesmez.

ön başlatma ile örnek:

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

Sen tarafından bölünüyor rr0.0 olabilen. rrSıfır olup olmadığını kontrol edin ve paydada kullanmaktan başka makul bir şey yapın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.