2013-01-18 14 views
8

Lettore di lunga durata, scrittore prima volta.tipo/i di operando non supportato per *: 'numpy.ndarray' e 'numpy.float64'

Ho cercato in giro su google e lo stack overflow, ma non ero davvero in grado di trovare una risposta generale a questa domanda.

Ricevo un "tipo di operando non supportato per *: errore 'numpy.ndarray' e 'numpy.float64'" in python 2.7.3 utilizzando numpy 1.6.2.

L'errore deriva dal moltiplicare un array numpy e un numpy float, ma non succede ogni volta.

Ad esempio:

x = np.tan(1) # numpy.float64 
y = np.array([0,1,2,3]) # numpy.ndarray 
np.multiply(x,y) # works no problem 

O

x = np.tan(np.abs(np.multiply(-31,41))) # numpy.float64 
y = np.square(np.add(np.divide(np.zeros(100),42),(-27)**40)) # numpy.ndarray 
np.multiply(x,y) # works no problem 

Entrambi lavorano

Ora per i bambini difficili:

np.multiply(np.square(np.add(np.divide(np.zeros(100),42),-27)**40)), 
np.tan(np.abs(np.multiply(-31,41)))) 

o, con x definiti come sopra:

np.multiply(np.square(np.add(np.divide(np.zeros(100),42),(-27)**40)),x) 

entrambi producono l'errore: NotImplemented

So che le funzioni e numeri casuali sembrano strano, ma concettualmente questo dovrebbe funzionare ancora, come ha funzionato quando entrambi sono stati fissati alle variabili individualmente.

Perché succede? Come posso risolverlo in senso generale?

Grazie mille! Jason

+0

Penso che tu abbia preso un bug nel codice, si può decidere di segnalarlo alla persone intorpidite. Per la cronaca, se 'a' è' np.ndarray' e 'x' è' np.float64', quindi entrambi 'x * a' e' a * x [...] 'funzionano, ma nessuno di' a * x', 'a + x',' a/x' o 'a - x' fare. È difficile capire perché, se il metodo '__mul__' di' a' non è in grado di gestirlo, '__rmul__' di' x' non viene chiamato, in quanto sembra sapere come gestire il caso ... – Jaime

+0

Grazie mille per controllandolo per me. Proverò a segnalarlo come un problema in numpy. Pensi che ci possa essere un modo per aggirare questo problema? – Jason

+0

Se si sostituisce 'x' con' x [...] 'funziona, ma è un brutto scherzo ... – Jaime

risposta

7

Ho il sospetto che il problema qui è che NumPy non può memorizzare i valori di Python long nei suoi array. Non appena si prova a farlo, passa il tipo di dati dell'array a object. Le operazioni aritmetiche sull'array diventano quindi più complicate perché NumPy non può più eseguire l'aritmetica stessa.

>>> np.array(27**40) 
array(1797010299914431210413179829509605039731475627537851106401L, dtype=object) 
>>> np.array(27**40) * np.tan(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'numpy.float64' 

Stranamente, scambiando l'ordine degli argomenti a volte può funzionare:

>>> np.tan(1) * np.array(27**40) 
2.7986777223711575e+57 

In questo secondo caso, il tipo del risultato è un pitone float, non una matrice NumPy.

La correzione è per evitare di creare long valori in array NumPy, e utilizzare float s invece:

>>> np.array(27.0**40) 
array(1.797010299914431e+57) 
>>> np.array(27.0**40) * np.tan(1) 
2.7986777223711575e+57 
>>> np.multiply(np.square(np.add(np.divide(np.zeros(10),42),(-27.0)**40)),np.tan(1)) 
array([ 5.02925269e+114, 5.02925269e+114, 5.02925269e+114, 
     5.02925269e+114, 5.02925269e+114, 5.02925269e+114, 
     5.02925269e+114, 5.02925269e+114, 5.02925269e+114, 
     5.02925269e+114]) 

Se ottenete un errore come questo è il futuro, la prima cosa da fare è controllare il dtype della matrice moltiplicata. Contiene valori NumPy o oggetti Python?

+0

Buona chiamata! La mia variabile array (y = np.square (np.add (np.divide (np.zeros (100), 42), (- 27) ** 40)) come definito sopra nella mia domanda) ha tipo 'oggetto' (y.dtype) Purtroppo non sono sicuro di poterlo forzare ad essere un float, considerando che inizia come un float, e da qualche parte lungo la strada si getta a lungo. – Jason

+0

È l'operazione con '(-27) ** 40' che è il problema. NumPy non può gestire direttamente Python 'long's. Tuttavia, puoi usare 'np.array' per convertire una matrice NumPy in un'altra matrice di un tipo diverso. Ad esempio, 'np.array (np.array (27 ** 40), dtype = np.float64)' restituirà un array di tipo 'float64'. –

+0

Sì, sono stato in grado di trovare dove sono stati generati gli ints 27 e 40 nel mio codice e li ho lanciati come float. Per il record np.arange genera int32. La maggior parte delle funzioni numpy funzionano in float, inclusi np.ones e np.zeros – Jason

-1

È un quiz? Non capisco perché la domanda sia così offuscata ... Tutto si riduce a questo semplice fatto.

Dato

>>> x = 10**100 
>>> type(x) 
<type 'long'> 
>>> y = np.float64(1) 

abbiamo

>>> y.__mul__(x) 
1e+100 
>>> y.__rmul__(x) 
NotImplemented 

Questo è il bug (o funzione, non so) dal momento che dovrebbe essere y.__mul__(x) == y.__rmul__(x) (almeno per questi particolari valori di x e).

Python long non sa come gestire la moltiplicazione con numpy.float64 (ma questo è corretto.)

>>> x.__mul__(y) 
NotImplemented 
>>> x.__rmul__(y) 
NotImplemented 

Così y*x viene valutato come y.__mul__(x) e dà il risultato atteso. Al contrario, x*y viene prima provato come x.__mul__(y) (non implementato, OK) rispetto a y.__rmul__(x) (non implementato ma un bug.).

Come già sottolineato, possiamo avere nd.arrays di oggetti arbitrari e tutto diventa chiaro.

Modifica

Questo bug è stato corretto (probabilmente nel NumPy ver 1.7.):

>>> np.version.version 
'1.13.1' 
>>> x = 10**100 
>>> y = np.float64(1) 
>>> x.__mul__(y) 
NotImplemented 
>>> x.__rmul__(y) 
NotImplemented 
>>> y.__mul__(x) 
1e+100 
>>> y.__rmul__(x) 
1e+100 
>>> x*y 
1e+100 
>>> y*x 
1e+100 
+0

Perché è downvoted? – Worthy7

+0

@ Worthy7 Non ho idea del motivo per cui la mia risposta è stata downvoted: IMHO identifica il bug insopportabile responsabile del comportamento imprevisto, come confermato da https://github.com/numpy/numpy/issues/2930#issuecomment-12445232 (e no, I non ha scritto la mia risposta dopo aver letto quel numero insensibile.) –

Problemi correlati