Newsgroup: it.comp.lang.c
Titolo: HELP:Zeri di funzione

Salve, qualcuno ha un programma in C oppure  in C++ che calcola gli zeri di
una funzione generica non polinomiale?

Salve, qualcuno ha un programma in C oppure in C++che calcola gli zeri di
una funzione generica non polinomiale    ( nel mio caso   f(X)= (1/X)  +
0.4 - 1.74xlog(10xsqrt(X)))   con uno qualsiasi dei metodi di
approssimazione ad esempio quello di Newton o delle tangenti, metodo delle
secanti,metodo delle bisezioni,oppure un altro qualsiasi? GRAZIE

Non so neache di cosa parli...
-- 
IL RAZZIATORE,
The Only good Windows is an Unistalled Windows
-----------------------------------------------------
EMAIL: 
razzi...@usa.net
WEB:   
www.geocities.com/il_razziatore/
 
razziatore.eyep.net
 (dalle 20.00 alle 8.00)
ICQ:   67552596



Cerca "numerical recipes in C", dovresti trovare qualcosa che fa al caso
tuo...
-- 
 Ciao, Bianco.
 Reply to luca.bianco (at) 
tiscalinet.it

Come sai, ogni metodo ha i suoi pregi e i suoi difetti:
la bisezione funziona con poche ipotesi, ma ha un ordine di
convergenza pari a 1; il metodo delle secanti con le sue scelte di
coefficienti producono vari procedimenti ("Regula Falsi", "Secanti",
"Newton", ..).
Poi ci sono i metodi di accelerazione di Aitken con l'algoritmo di
Steffensen, ...
Il modo migliore sarebbe quello di usare una combinazione di questi
metodi. Per esempio usare le secanti per stabilire un primo punto di
approssimazione della radice e poi proseguire con Steffensen.
Dimmi tu cosa ti occorre.
Eccoti la bisezione: stai attento ai valori ammissibili per il calcolo
della tua f(x); ho provveduto ai numerosi errori di approssimazione
inserendo un conteggio massimo sulle iterazioni.
Abbi cura solo di scegliere una funzione continua, e un intervallo
agli estremi del quale la funzione ha segno opposto.
Queste solo le uniche condizioni richieste dal metodo.
============================================
#include "stdio.h"
#include "math.h"
#include "float.h"
#include "stdlib.h"
double f(double x)
{
 return( (1/x)+0.4-1.74*x*log(10*x*sqrt(x)) );
}
double bisezione(double a, double b, double toll, long max_iterazioni)
{
/* la funzione e' calcolata dalla funzione double f(double) */
double radice;
long n;
 if (f(a)*f(b)<0) {
  n=0;
  do {
   radice = (a+b)/2.0;
   printf("\n%ld: [ %f , %f ]  ->  %lf",++n,a,b,radice);
   if ( f(a)*f(radice)<0 )
    b=radice;
   else
    a=radice;
  } while(toll<fabs(b-a)/2.0 && n<max_iterazioni);
 } else {
  printf("\nErrore nella scelta dell'intervallo\n");
  exit(1);
 }
 return(radice);
}
void main(void)
{
 long iterazioni;
 double a , b , errore_ass;
 printf("\nQuante iterazioni al piu' vuoi eseguire? ");
 scanf("%ld",&iterazioni);
 printf("\nQuale e' l'errore che intendi tollerare? ");
 scanf("%lf",&errore_ass);
 printf("\nintervallo sinistro di ricerca:\n");
 scanf("%lf",&a);
 printf("\nintervallo destro   di ricerca:\n");
 scanf("%lf",&b);
 printf("\n\nRadice: %f\n\n",bisezione(a,b,errore_ass,iterazioni));
}

A gentile richiesta ... :-))) ... si replica con il metodo delle
SECANTI.
Questo metodo, come quello di bisezione, richiede la continuita' della
funzione f(x) in un opportuno intervallo [a,b] in cui e' presente una
radice, ovvero f(a)*f(b)<0.
Come dato aggiuntivo, il metodo delle secanti necessita di una
approssimazione della radice 'x0' di f(x) da cui partire (puoi usare
il metodo di bisezione, oppure uno dei due estremi dell'intervallo).
Puo' prevedere due controlli di "tolleranza" della soluzione, sia
sull'asse dell'ascisse che su quello delle ordinate; per questo
semplice esempio ho provveduto solo al secondo, tramite controllo di
errore assoluto.
Partendo da 'x0' si crea una successione di punti ottenuti
dall'intersezione dell'ascisse con la secante/tangente passante per
f(x0) , ..... , f(xn).
Il coefficiente angolare di questa retta determina anche il metodo e
la relativa efficienza:
1) "Regula Falsi" : ordine di convergenza = 1
2) "Metodo delle Secanti" : ordine di conv. = 1.618
3) "Newton/tangenti" : odine di conv. = 2 (richiede la conoscenza di
f'(x) )
Sempre per semplicita', ho impostato l'approssimazione della prima
radice, con un estremo dell'intervallo.
(L'algoritmo produce la seguente soluzione 0.658292 ... per la tua
funzione)
=======================================
double secanti(double a, double b, double toll, long max_iterazioni)
{
/* la funzione e' calcolata dalla funzione double f(double) */
double radice;
long n;
 if (f(a)*f(b)<0) {
  n=0;
  radice=a;
  do {
   /* l'espressione sotto e' volutamente espressa in questo modo
      per limitare la propagazione dell'errore  */
   radice=(a*f(b)-b*f(a))/(f(b)-f(a));
   if ( f(b)*f(radice)<0 )
    a=radice;
   else
    b=radice;
  } while(toll<fabs(f(radice)) && ++n<max_iterazioni);


Ciao, dal momento che ho sbagliato a scrivere la funzione, ti do quella
corretta:
(1/x)+0.4-1.74*log(R*sqrt(x)). Come vedi c'è è stato qualche malinteso per
quanto riguarda le moltiplicazioni e l' incognita x.Ho provato a cambiare la
funzione nel testo che mi hai mandato ma mi da errore, se puoi essere ancora
cosi gentile da ricontrollare il tutto, aggiungendo anche la condizione che
R  deve valere 10000, 100000 e 1000000. Grazie