RuntimeWarning: nilai tidak valid ditemukan dalam pembagian

96

Saya harus membuat program menggunakan metode Euler untuk model "bola di musim semi"

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

Saya terus mendapatkan kesalahan ini:

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

Saya tidak bisa memahaminya, apa yang salah dengan kodenya?

Bogdan Osyka
sumber
cetak apa yang terjadi di setiap item yang lebih kecil di baris kode tersebut. Itulah satu-satunya cara untuk men-debugnya.
CppLearner
2
Anda memiliki nans untuk rr, yang membuang kesalahan itu. Masalah dengan rrberasal dari r[i,:]mana yang sama, dalam beberapa kasus, dengan array([ nan, nan]). Seperti yang disebutkan @CppLearner, cara terbaik untuk men-debug (atau menulis) kode adalah dengan menguji setiap bagian yang lebih kecil sebelum menerapkan.
cosmosis

Jawaban:

161

Saya pikir kode Anda mencoba untuk "bagi dengan nol" atau "bagi dengan NaN". Jika Anda menyadarinya dan tidak ingin hal itu mengganggu Anda, maka Anda dapat mencoba:

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

Untuk lebih jelasnya lihat:

Yan Zhu
sumber
76
Ini dapat berguna untuk digunakan with NP.errstate(divide='ignore',invalid='ignore'):jika Anda ingin menyembunyikan peringatan untuk satu blok kode.
GWW
8
Mengapa seseorang ingin mengabaikan pembagian dengan nol atau NaN?
x kuadrat
7
@xsquared Ketika Anda sendiri menangani nilai dengan benar, setelah pembagian, dan Anda mendistribusikan kode Anda ke pengguna (atau lelah melihat peringatan). with np.errstate(...)memungkinkan Anda melakukan ini dengan aman hanya untuk kasus yang ditangani.
reve_etrange
2
@reve_etrange Yang saya temukan jauh lebih dapat diterima daripada umumnya mengabaikan membagi dengan nol.
x kuadrat
1
lebih baik untuk mengatur ini sebelum baris yang menyebabkan kesalahan kemudian reset setelah baris ke keadaan normal 'warn'dengan perintahnp.seterr(divide='warn', invalid='warn')
Mohammad ElNesr
15

Pengindeksan Python dimulai dari 0 (bukan 1), jadi tugas Anda "r [1 ,:] = r0" mendefinisikan elemen kedua (yaitu indeks 1) dari r dan meninggalkan elemen pertama (indeks 0) sebagai sepasang nol. Nilai pertama i di perulangan for Anda adalah 0, jadi rr mendapatkan akar kuadrat dari hasil perkalian titik dari entri pertama di r dengan dirinya sendiri (yaitu 0), dan pembagian dengan r di baris berikutnya menghasilkan kesalahan.

Kinch
sumber
10

Untuk mencegah pembagian dengan nol Anda dapat melakukan pra-inisialisasi keluaran 'keluar' di mana kesalahan div0 terjadi, misalnya np.wheretidak memotongnya karena garis lengkap dievaluasi terlepas dari kondisinya.

contoh dengan pra-inisialisasi:

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
sumber
4

Anda membagi rryang mungkin menjadi 0,0. Periksa apakah rrnol dan lakukan sesuatu yang masuk akal selain menggunakannya di penyebut.

crayzeewulf
sumber