2011-12-06 13 views
9

Esperti;Come dire a Mathematica di sostituire 0 per alimentare 0 per 1?

Dato

f = (#1^#2) & 

C'è un modo per definire 'f' sopra tale che se # 1 e # 2 sono entrambi pari a zero, allora il valore della funzione pura 'f' dovrebbe essere 1?

in modo che quando scrivo

f[0,0] 

tornerà 1 e non indeterminato?

btw, so che posso scrivere

f = (If[#1 == 0 && #2 == 0, 1, #1^#2]) & 

Ma volevo una regola generale o modello, quindi non c'è bisogno di scrivere queste verifiche, in quanto la funzione di pura può essere più complicato (molti # in esso) e non voglio eseguire molti di questi controlli "se non altro" per ogni possibile 0^0 che potrebbe apparire.

grazie

Aggiornamento:

Può essere Vorrei chiarire di più perché sto facendo questo.
Ho un utente seleziona una funzione da un menu. La funzione è

a x^n0 + b y^n1 + c x^n2 y^n3 

Dove in quanto sopra, i parametri 'n0', 'n1', 'n2' e 'n3' può anche essere scelti tra cursori, e questi possono essere zero.

Ora, 'x' e 'y' sono coordinate, e anche queste possono essere zero.

Pertanto, è possibile che si verifichi 0^0 durante la valutazione della funzione precedente.

Ci sono molti casi da controllare, quando lo faccio da solo. Ad esempio 'y^n3' può essere 0^0 e non l'altro, y^n1 può essere 0^0 e non l'altro, x^n2 y^n3 può essere sia 0^0 che non gli altri, ecc. e quindi devo definire molti casi diversi. (16 possibili casi penso).

E sto cercando di evitarlo. Se posso dire a Mathematica di sostituire 0^0 per 1 a un livello inferiore, la vita sarà più semplice.

Aggiornamento 12/7/11 Grazie per le risposte e i commenti di tutti, sono tutti molto utili e risolvono il mio problema e ho imparato da loro.

Ho selezionato la risposta di Leonid in quanto mi ha consentito di risolvere il problema con una quantità minima di codice aggiuntivo.

Ecco un piccolo esempio

Manipulate[Row[{format[x, n], "=", eval[x, n]}], 
{{x, 0.0, "x="}, 0, 1, .1, Appearance -> "Labeled"}, 
{{n, 0.0, "n="}, 0, 1, .1, Appearance -> "Labeled"}, 
Initialization :> 
    (
    format[x_, n_] := HoldForm["(" x ")"^n]; 
    eval = Unevaluated[#1^#2] /. HoldPattern[0.0^0.0] :> 0.0 & 
    ) 
] 

Io uso i numeri reali in tutto il mondo nel mio codice (si tratta di un PDE risolutore numerico), così che è il motivo per cui ho usato 0.0 in quanto sopra e non 0^0 per adattarsi con quello che sto facendo.

enter image description here

+2

Sei sicuro di voler eseguire l'eval a 1 e non 0? La notazione fa sembrare che stiate valutando polinomi dove gli esponenti sono inte gretti o forse reali. Considerazioni sulla continuità indicano che un valore di 0 potrebbe essere preferibile in tale scenario. –

+0

@DanielLichtblau, Ok, grazie, cercherò 0^0 essere sostituito da 0 invece di 1. Ma in entrambi i casi, se uso IF THEN ELSE (o il suo equivalente funzionale definendo molte firme diverse per ogni possibile caso), ci sono ancora 16 casi diversi. Speravo che ci fosse un modo per cortocircuitarlo, ma dire a Mathematica di sostituire 0^0 con X dove X è la scelta giusta (0 o 1 come potrebbe essere). – Nasser

+0

Vedere anche questa discussione in mathgroup: http://mathforum.org/kb/message.jspa?messageID=6577581&tstart=0 e questa domanda sui programmatori SE: http://programmers.stackexchange.com/questions/9788/how- does-language-x-handle-indeterminate-forms-like-00 –

risposta

10

Sono d'accordo con la risposta di @Deep giallo, ma se ti ostini a una funzione di pura, qui è un modo:

f = Unevaluated[#1^#2] /. HoldPattern[0^0] :> 1 & 

EDIT

Rimanendo all'interno del regno delle funzioni pure, la situazione descritta nella modifica può essere indirizzata allo stesso modo della mia soluzione al tuo specifico esempio originale. È possibile automatizzare questo con un po 'di metaprogrammazione, che definisce la seguente funzione del trasformatore:

z2zProtect[Function[body_]] := 
    Function[Unevaluated[body] /. HoldPattern[0^0] :> 1] 

Poi, il mio codice precedente può essere riscritto come:

f = z2zProtect[#1^#2 &] 

Ma è possibile è questo, più in generale, per esempio:

ff = z2zProtect[#1^#2 + 2 #2^#3 + 3 #3^#4 &] 

In[26]:= ff[0,0,0,0] 
Out[26]= 6 
+0

+1 Nice, anche se mi permetto di sottolineare che 'f [foo, 0]' restituisce '1' per' foo' indefinito. –

+0

@Deep Yellow Grazie per l'upvote. Per quanto riguarda il tuo commento - questo è come previsto, ed è basato su una regola incorporata per 'Power', non sulla mia particolare definizione. La tua soluzione presenta lo stesso comportamento. –

+0

Oh sì :-) * Mathematica * presuppone che le espressioni indefinite non siano uguali a zero per 'Power'. –

4

Si può provare a scriverlo come f = Quiet[Check[#1^#2,1]] &.

Quiet sopprimerà il messaggio "Power::indet: "Indeterminate expression 0^0 encountered." e Check sostituirà il risultato con 1 se è indeterminato.

Probabilmente è meglio usare alcune funzioni come s = Quiet[Check[#1, 1]] e racchiudere le espressioni in esso.

+5

Si noti che questo sopprimerà anche tutto ciò che produce lo stesso errore e l'output 1, indipendentemente dal fatto che si tratti del risultato desiderato. Ad esempio, 'f [0, I]'. – abcd

16

Naturalmente ci sono molti modi per fare cose in Mathematica, ma un linguaggio di progettazione che uso spesso è scrivere la "funzione" (in realtà, un modello) con specificità decrescente. Mathematica ha la proprietà che applicherà modelli più specifici prima meno specifici.

Quindi, per il vostro caso avevo appena scritto:

Clear[f]; 
f[0, 0] = 1; 
f[a_, b_] := a^b; 

presumo che ci si aspetta di lavorare con valori interi dato che è il contesto abituale per questo tipo di situazione, per esempio quando si valutano le funzioni di base di Bernstein.

+0

+1 Risposta buona e chiara senza fronzoli. A proposito, penso che intendevi dire "con specificità decrescente". – DavidC

+0

@DavidCarraher: Grazie, corretto. –

3

sto un po 'sorpreso il banale (anche se di poco pericoloso) correzione non ha ottenuto menzionato in precedenza. Se davvero non ti aspetti che l'espressione 0^0 venga visualizzata in qualsiasi contesto in cui ti preoccupi (a) di farlo, o (b) vorresti che valuti qualcosa di diverso da 1, puoi semplicemente provare

Unprotect[Power]; 
Power[0, 0] = 1; 
Protect[Power]; 
0^0 

ho bisogno questa correzione in una situazione in cui una funzione complicata aveva un numero di chiamate espressioni della forma x^n dove x è reale e n è un intero, nel qual caso 0^0 deve essere visto come limite di x^0=1 come x passa a 0.

È importante notare, tuttavia, che facendo questo si "contaminano" Power per la sessione del kernel corrente e potrebbe quindi interrompere altri notebook che vengono eseguiti contemporaneamente e per i quali le condizioni (a) e (b) potrebbero non essere valide.Poiché Power si trova nel contesto System՝ anziché Global՝, potrebbe essere difficile separare i contesti di diversi notebook per evitare gli scontri prodotti da questa correzione.