2012-01-28 14 views
12

Sto avendo qualche strano comportamento nel mio codice Python relativo a - e -=. Sto scrivendo una decomposizione QR utilizzando NumPy, e ho la seguente riga di codice in un doppio ciclo:- vs - = operatori con numpy

v = v - r[i,j] * q[:,i] 

dove q e r sono entrambi numpy.array e v è una fetta di un altro numpy.array preso come v = x[:,j].

Il codice sopra riportato non funziona come previsto in tutti i casi. Tuttavia, se faccio la seguente modifica:

v -= r[i,j] * q[:,i] 

Poi tutto funziona perfettamente.

Ho avuto l'impressione che quelle due linee dovrebbero essere identiche. Per verificare se -= e _ = _ - stavano lavorando in modo diverso, ho creato il seguente frammento

import numpy 

x = numpy.array(range(0,6)) 
y = numpy.array(range(0,6)) 

u = x[3:5] 
v = y[3:5] 

print u,v 

u = u - [1,1] 
v -= [1,1] 

print u,v 

che funziona ancora come previsto, producendo [2 3] [2 3] ad entrambe le istruzioni di stampa.

Quindi sono del tutto confuso perché quelle due linee hanno prestazioni diverse. L'unica cosa che posso pensare è che a volte ho a che fare con numeri estremamente piccoli (dell'ordine di 10^-8 o più piccoli) e c'è qualche problema di precisione a cui è meglio -=? La prima riga peggiora sempre di più man mano che gli elementi di x diventano più piccoli.

Mi scuso se ci sono altri post su questo problema simile, non riesco a cercare - e -= e non so se ci sono termini corretti per questi oltre a compiti/operatori.

Grazie per qualsiasi aiuto!

+4

Per riferimento futuro, se si desidera effettuare la ricerca per cose come questa i nomi per '' -' e - = 'sono [' __sub__'] [1] e [ '__isub__'] [2] rispettivamente. Quindi: 'a = a - b' è equivalente a' a = a .__ sub __ (b) ' ' a - = b' è equivalente a 'a .__ isub __ (b)'. (a meno che __isub__ non sia definito, ricade su quanto sopra) [1]: http://pyref.infogami.com/__add__ [2]: http://pyref.infogami.com/__iadd__ –

risposta

19

Quando v è una sezione, quindi v -= X e v = v - X producono risultati molto diversi. Considerare

>>> x = np.arange(6) 
>>> v = x[1:4] 
>>> v -= 1 
>>> v 
array([0, 1, 2]) 
>>> x 
array([0, 0, 1, 2, 4, 5]) 

dove v -= 1 aggiorna la fetta, e quindi la matrice che si vede, sul posto, vs.

>>> x = np.arange(6) 
>>> v = x[1:4] 
>>> v = v - 1 
>>> v 
array([0, 1, 2]) 
>>> x 
array([0, 1, 2, 3, 4, 5]) 

dove v = v - 1 reimposta la variabile v lasciando x intatta. Per ottenere l'ex risultato senza -=, dovreste fare

v[:] = v - 1 
+0

Grazie, questo chiarisce un sacco di confusione per me. –

11

È possibile ottenere risultati diversi da x - y e x -= y se i tipi di dati di x e differiscono.

Ad esempio:

import numpy as np 

x = np.array(range(0,6)) 
y = np.array(np.arange(0,3,0.5)) 

print x - y 
x -= y 
print x 

Questo stampa:

[ 0. 0.5 1. 1.5 2. 2.5] 
[0 0 1 1 2 2] 

può valere la pena rendere sicuro il vostro array dtypes sono esattamente come ci si aspetta (ad esempio, non sei inavvertitamente usando intero o float32 array invece di float64), prestando particolare attenzione agli array utilizzati sul lato sinistro di -=.

+1

+1 anche se questo risulta non essere la ragione; Ho trascurato completamente questa possibilità, e non avrei dovuto. – DSM

4

+1 a entrambi gli altri risposte a questa domanda. Coprono due importanti differenze tra = e -= ma volevo evidenziarne un'altra. La maggior parte delle volte x -= y corrisponde a x[:] = x - y, ma non quando x e sono sezioni dello stesso array. Per esempio:

x = np.ones(10) 
y = np.ones(10) 

x[1:] += x[:-1] 
print x 
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.] 

y[1:] = y[1:] + y[:-1] 
print y 
[ 1. 2. 2. 2. 2. 2. 2. 2. 2. 2.] 
+0

Questo è incredibilmente stupido. Puoi spiegare come viene il primo risultato? –