Problema con funzione Matlab

One2
Nel programma che sto' scrivendo per il calcolo delle radici di un equazione utilizzando la "regula falsi" pongo:
f=inline(funz);
dove funz è una stringa.Più avanti nel programma pongo
f(a(i+1))=f(c(i));
.Eseguendo il codice mi da come risultato
 The following error occurred converting from double to inline,Input must be a string 
.Allora ho provato a modicare la funzione così
f(a(i+1))=num2str(f(c(i)));
in modo che $f(c(i))$sia trasformata in stringa.Purtoppo continua a darmi errore. :|

Risposte
Lory314
"One":


f(a(i+1))=f(c(i));




Questo penso abbia poco senso. a e c penso siano due vettori (di interi? o reali?). Supponiamo che a(i+1)=N e c(i)=M.
Con questa istruzione stai assegnando(?) a f(N) il valore f(M).
Prova a scrivere e spiegare quello che vorresti fare; probabilmente riuscirai da solo a capire quello che non va.

One2
Con questa istruzione stai assegnando(?) a f(N) il valore f(M).

Si...$a$ e $b$ sono reali e rappresentano gli estremi di un intervallo (che inizia da $a$ e finisce in $b$), $c$ viene calcolato con la formula $c(i) = ((f(b(i))*a(i))-(f(a(i))*b(i)))/(f(b(i))-f(a(i)))$.Se risulta $f(b(i))*f(a(i)) <0$ devo porre $f(a(i+1))=f(a(i))$ e $f(b(i+1))=f(c(i))$.L'algoritmo è quello del metodo "regula falsi".

Lory314
Io questo metodo non l'ho mai usato. Ho letto ora su internet come funziona e da quanto ho capito è un misto tra il metodo di bisezione e il metodo delle secanti. Continuo, comunque, a rimanere perplesso quando dici che devi porre $f(a(i+1)) = f(a(i))$ e $f(b(i+1))=f(c(i))$. Probabilmente sbaglio io dato che non conosco il metodo, ma da un punto di vista matematico mi sembra strana come cosa. Per ora ti consiglio di dare un'occhiata alla sezione Numerical Analysis di
http://en.wikipedia.org/wiki/False_position_method
e al codice che è scritto più avanti.
Su wikipedia in spagnolo c'è anche un codice in Java che ad occhio mi sembra più chiaro di quello in C.

One2
Continuo, comunque, a rimanere perplesso quando dici che devi porre f(a(i+1))=f(a(i)) e f(b(i+1))=f(c(i)).
Hai ragione!Ho letto male io l'algoritmo che avevo sul mio libro...e ci ho perso quasi una giornata :|

Approfitto per chiedere delucidazioni su un errore che mi da ora il programma di cui parlavo prima:
function [x0]=regulafalsi(funz,a,b,max1,toll)
f=inline(funz);
fprintf('Inizio REGULA FALSI')
cont=1;
.
.
.
.
for (i=1:max1)
c(i) = ((f(b(i))*a(i))-(f(a(i))*b(i)))/(f(b(i))-f(a(i)));
    if (f(c(i))==0)
	  x0=c(i);
	  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
	elseif (f(c(i))*f(a(i))<0)
	  a(i+1)=a(i);
	  b(i+1)=c(i);
	  cont=cont+1;
	else
	  a(i+1)=c(i);
	  b(i+1)=b(i);
	  cont=cont+1;
	end
	if (i>1)
	  if (abs(f(c(i))-f(c(i-1))) < toll)
	    x0=c(i);
		fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
	  end
	end  
end	

Come errore mi da Function definitions are not permitted in this context..Qualcuno sa dirmi perchè?

Lory314
Io non ottengo quell'errore. Non capisco, inoltre, quei 4 punti dopo cont=1.
Ti consiglio comunque di inserire dopo gli fprintf il comando break in modo che quando trova la soluzione esce dal ciclo e non continui a fare itereazioni.

One2
Non capisco, inoltre, quei 4 punti dopo cont=1.

I quattro punti,gli ho messi per saltare una piccola parte di codice secondo me ininfluente.
Io non ottengo quell'errore.

A te funziona?A me continua a darmi il solito errore.
Ti consiglio comunque di inserire dopo gli fprintf il comando break

Ho messo $return$ invece che $break$,perchè mi pare che $break$ lo accettasse solo se dentro un ciclo....



Posto il programma per intero:
function [x0]=regulafalsi(funz,a,b,max1,toll)
f=inline(funz);
fprintf('Inizio REGULA FALSI')
cont=1;
if a >= b
   ('ATTENZIONE: a>=b'),
   return,end
if f(a)*f(b)>0
   ('ATTENZIONE: f(a)*f(b) >0'),
	return,end
if (f(a)==0)
  x0=a;
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
end
if (f(b)==0)
  x0=b;
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
end

for (i=1:max1)
c(i) = ((f(b(i))*a(i))-(f(a(i))*b(i)))/(f(b(i))-f(a(i)));
 cont=cont+1;
    if (f(c(i))==0)
	  x0=c(i);
	  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
	  return
	elseif (f(c(i))*f(a(i))<0)
	  a(i+1)=a(i);
	  b(i+1)=c(i);
	else
	  a(i+1)=c(i);
	  b(i+1)=b(i);
	end
	if (i>1)
	  if (abs(f(c(i))-f(c(i-1))) < toll)
	    x0=c(i);
		fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',x0,cont)
		return
	  end
	end  
end	

Lory314
A me non dà nessun errore, ma penso che questo possa dipendere dall'esempio su cui stiamo testando.
Prova a postare la tua chiamata della funzione così posso vedere che funzione e valori stai utilizzando.
Comunque, a parte nei tre if iniziali, break funziona perchè sei dentro un ciclo.

One2
Dati:
funz = '-x^2+5*x+2';
max1=100;
toll = 1e-6;
a=0;
b=6;

Chiamata:
function [x0]=regulafalsi(funz,a,b,max1,toll)

Errore:
 function [x0]=regulafalsi(funz,a,b,max1,toll)
           |
Error: Function definitions are not permitted in this context.

Infine ho cambiato il test d'arresto così:
if ((abs(c(i)-c(i-1)) < tollx) || (abs(f(c(i))) < tollf))

Questo è il programma aggiornato:
function [x0]=regulafalsi(funz,a,b,max1,tollx,tollf)
f=inline(funz);
fprintf('Inizio REGULA FALSI')
cont=1;
if a >= b
   ('ATTENZIONE: a>=b'),
   return,end
if f(a)*f(b)>0
   ('ATTENZIONE: f(a)*f(b) >0'),
	return,end
if (f(a)==0)
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',a,cont)
end
if (f(b)==0)
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',b,cont)
end

for (i=1:max1)
c(i) = ((f(b(i))*a(i))-(f(a(i))*b(i)))/(f(b(i))-f(a(i)));
cont=cont+1;
    if (f(c(i))==0)
	  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',c(i),cont)
	  return
	elseif (f(c(i))*f(a(i))<0)
	  a(i+1)=a(i);
	  b(i+1)=c(i);
	else
	  a(i+1)=c(i);
	  b(i+1)=b(i);
	end
	if (i>1)
	  if ((abs(c(i)-c(i-1)) < tollx) || (abs(f(c(i))) < tollf))
		fprintf('Il valore della radice è %6.10g \t calcolato in %6.0g \ passi',c(i),cont)
        return
      elseif
          x0=c(i);
	  end
	end  
end	

Lory314
Allora, il motivo dell'errore è che chiami la funzione in modo sbagliato. Quando chiami la dunzione non devi riscrivere la parola chiave function prima della variabile x0.
La chiamata giusta è:
[x0]=regulafalsi(funz,a,b,max1,toll)


Poi attento alle modifiche che hai fatto. Se hai definito delle nuove varibili tollx e tollf ricordati che o vanno dichiarate da qualche parte o devi metterle come input.

One2
Allora, il motivo dell'errore è che chiami la funzione in modo sbagliato.

:oops:
Poi attento alle modifiche che hai fatto. Se hai definito delle nuove varibili tollx e tollf ricordati che o vanno dichiarate da qualche parte o devi metterle come input.

OK.
Grazie

One2
Vorrei evitare ti aprire un'altro post,quindi scrivo qui il mio attuale problema:
Sto facendo un metodo per calcolare le radici di un equazione tramite la "Regula falsi",qui sotto metto il mio prpogramma:
function [x0]=regulafalsi(funz,a,b,max1,tollx,tollf)
f=inline(funz);
fprintf('Inizio calcolo radice con metodo REGULA FALSI \n')
cont=0;
if a >= b
   ('ATTENZIONE: a>=b');
   return,end
if f(a)*f(b)>0
   ('ATTENZIONE: f(a)*f(b) >0');
	return,end
if (f(a)==0)
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0d \t passi',a,cont-1)
  return
  end
if (f(b)==0)
  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0d \t passi',b,cont-1)
  return  
  end

for (i=1:max1)
c(i) = ((f(b(i))*a(i))-(f(a(i))*b(i)))/(f(b(i))-f(a(i)));
cont=cont+1;
    if (f(c(i))==0)
	  fprintf('Il valore della radice è %6.10g \t calcolato in %6.0d \t passi',c(i),cont-1)
	  return
	elseif (f(c(i))*f(a(i))<0)
	  a(i+1)=a(i);
	  b(i+1)=c(i);
	else
	  a(i+1)=c(i);
	  b(i+1)=b(i);
	end
	if (i>1)
	  if ((abs(c(i)-c(i-1)) < tollx) || (abs(f(c(i))) < tollf))
		fprintf('Il valore della radice è %6.10g \t calcolato in %6.0d \t passi \n',c(i),cont-1)
        x0=c(i);
        return
      else
          x0=c(i);
	  end
	end  
end	
end

Dove funz è la funzione,a e b sono gli estremi dell'intervallo,tollx e tollf le tolleranze e max1 il numero massimo di passi da fare.
Quando eseguo il programma mi appare il seguente errore:
Error in regulafalsi (line 2)
f=inline(funz);

Quindi pare che non legga funz come funzione,anche se io ho messo in input
funz='-x^2+5*x+2'
.
Mi potete dare qualche consiglio?

Lory314
Penso di aver capito dov'è l'errore. Nei due IF iniziali fai stampare una stringa e poi fai return. Il problema è che la variabile che dovresti restituire, cioè x0, non ha alcun valore. Questo va fatto anche se il programma non entra in quei due IF, perchp se ci entrasse non saprebbe cosa fare. Infatti l'errore per intero che matlab ti dovrebbe dare non è solo quallo riportato da te ma

Error in ==> regulafalsi at 3
f=inline(funz);

??? Output argument "x0" (and maybe others) not assigned during call to
PathName file


Adesso, onestamente non so perchè identifichi l'errore con la linea 3 del codice, però la seconda parte dell'errore è utile.
Io ho provato a mettere in quei due IF, x0=NaN in modo da assegnare un valore a x che non si confonda con l'eventuale soluzione trovata e quell'errore mi è scomparso.

Ho notato un'altra cosa. Come ti ho detto non conosco questo algoritmo, quindi potrei sbagliarmi.
Potresti spiegarmi questa parte?
     if ((abs(c(i)-c(i-1)) < tollx) || (abs(f(c(i))) < tollf))
      fprintf('2 Il valore della radice è %6.10g \t calcolato in %6.0d \t passi \n',c(i),cont-1)
        x0=c(i);
        return
     else
        x0=c(i);
     end

Il mio dubbio è che sia nell'IF sia nell'ELSE assegni un valore ad x0 e questo valore sarà lo stesso indipendentemente dal fatto che tu sia nell'IF o nell'ELSE. L'unica differenza è che nel secondo caso continui a fare iterazioni dato che non c'è alcun return, nell'altro ti fermi perché la soluzione l'hai trovata. Quindi a mio avviso quell'else è inutile.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.