|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2001
Città: COMO, sul maestoso LARIO
Messaggi: 248
|
Funzione ERF in C++
Ciao gente.
Qualcuno mi sa dire dove posso recuperare una libreria C++ che contenga la funzione ERF, ossia l'integrale della gaussiana? Grazie!
__________________
Athlon FX-53 / MSI K8N Neo2 Platinum / Corsair TwinX 1024 XL / 2 x WesternDigital Raptor 74GB - RAID 0 / Gainward PowerPack! 2200 GeF. 6800 256MB / Pioneer DVR-108 / LiteOn LTR-52327S / Enermax 550W / HP P1100 21" CRT |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Sep 2001
Città: COMO, sul maestoso LARIO
Messaggi: 248
|
Dopo un po' di mosse penso di esserci arrivato:
il problema sta nel fatto che la funzione gaussiana non ha primitiva, quindi il calcolo dell'area sottesa è solo numerico: erf(x) non ha espressione analitica. La gaussiana standardizzata è un'esponenziale, quindi trasformabile in una serie uniformemente convergente su tutto R. Ho poi integrato per serie per approssimare la funzione a mio piacimento. Per avere una precisione fino a 10^(-4) è necessario sommare non meno di 15 termini della serie ottenuta, ma devo ammettere che non è poi tanto male. Ecco quindi l'espressione approssimata dell'area sottesa dalla gaussiana standardizzata in funzione di x (con f[0]=0). A partire da questa basta un bel ciclo FOR e il calcolo è fatto. A chi può servire: ![]() Se qualcuno ha un'idea migliore mi faccia sapere!
__________________
Athlon FX-53 / MSI K8N Neo2 Platinum / Corsair TwinX 1024 XL / 2 x WesternDigital Raptor 74GB - RAID 0 / Gainward PowerPack! 2200 GeF. 6800 256MB / Pioneer DVR-108 / LiteOn LTR-52327S / Enermax 550W / HP P1100 21" CRT |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Sep 2001
Città: COMO, sul maestoso LARIO
Messaggi: 248
|
E' sorto un altro problema; pensavo che una volta trovata una formula analitica per il calcolo il gioco fosse finito.
Ho provato a tradurre in C++ la funzione che ho riportato sopra nel modo più ovvio, ossia: ***************************************** long double normale(float x) { long double sum=0; for(i=0; i<=15; i++) sum=sum+(pow(2,-i)*pow(x,2*i+1)*pow(-1,i))/((2*i+1)*fatt(i)); return sum/sqrt(1/(2*3.1415926)); } ***************************************** ..che traduce la formula. Ma i valori ottenuti non sono soddisfacenti: la stessa equazione, in Derive, dà un risultato mooolto migliore. Ho provato allora ad eliminare il ciclo FOR, espcitando la sommatoria e scrivendo esplicitamente i coefficienti. In questo modo i valori sono nettamente più simili a quelli di Derive, ma non oltre x=0.7. Considerando che la normale è praticamente costante dopo x=3.7.... non ci siamo ancora. Come posso tradurre in C++ la formula dell'immagine in modo decente????? Grazie dell'aiuto!
__________________
Athlon FX-53 / MSI K8N Neo2 Platinum / Corsair TwinX 1024 XL / 2 x WesternDigital Raptor 74GB - RAID 0 / Gainward PowerPack! 2200 GeF. 6800 256MB / Pioneer DVR-108 / LiteOn LTR-52327S / Enermax 550W / HP P1100 21" CRT |
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Se non ricordo male ci sono degli algoritmi appositi per l'integrazione numerica, per renderla sia piu' veloce che piu' precisa.
Ora non chiedermi quali Hai provato a compilare senza le ottimizzazioni sui floating point ? |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Sep 2001
Città: COMO, sul maestoso LARIO
Messaggi: 248
|
Cosa intendi "senza le ottimizzazioni sui floating point"? Scusa ma sto perdendo lucidità....
__________________
Athlon FX-53 / MSI K8N Neo2 Platinum / Corsair TwinX 1024 XL / 2 x WesternDigital Raptor 74GB - RAID 0 / Gainward PowerPack! 2200 GeF. 6800 256MB / Pioneer DVR-108 / LiteOn LTR-52327S / Enermax 550W / HP P1100 21" CRT |
|
|
|
|
|
#6 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Intendevo dire che tra le ottimizzazioni del compilatore, spesso ce ne sono alcune che aumentano la velocita' sacrificando un po' la precisione sui floating point. Potresti vedere se nel tuo caso sono stato attivate ed eventualmente toglierle
( che compilatore usi ? ) |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Sep 2001
Città: COMO, sul maestoso LARIO
Messaggi: 248
|
All'inizio pensavo che fosse colpa di approssimazioni del compilatore... poi mi son messo a spezzare la formula, monitorando man mano come cambiava il valore ottenuto dal ciclo FOR. I termini che si aggiungono alla serie dovrebbero essere più piccoli man mano che si procede, se voglio che la serie converga.... ma invece ho visto che fluttuavano abbastanza casualmente....
In sostanza, l'errore non era dovuto nè al compilatore, nè all'algoritmo, ma semplicemente alla funzione fatt(x) che avevo importato da una vecchia libreria che avevo fatto..... in quella libreria avevo impostato la funzione fattoriale così: int fatt(int x) { ............} Ovviamente andava bene finchè i fattoriali da calcolare erano piccoli... ma nell'algoritmo compare anche 15! bastava modificare la funzione in modo che restituisse valori non interi<65535 (già 9!>65535............) Se dio vuole adesso la funzione restituisce i valori corretti.... basta stare attenti a ricordarsi che da x=3.9 circa in poi la funzione è identicamente = 0.5, mente l'algoritmo di sopra non è in grado di reggere oltre un certo intervallo perchè la successione non converge più a ERF(x). Ecco il grafico della serie calcolata fino al quindicesimo termine in rosso, che si sovrappone perfettamente al grafico della ERF(x) vera e propria (in nero, visibile agli estremi). ![]() Cmq grazie dell'aiuto!
__________________
Athlon FX-53 / MSI K8N Neo2 Platinum / Corsair TwinX 1024 XL / 2 x WesternDigital Raptor 74GB - RAID 0 / Gainward PowerPack! 2200 GeF. 6800 256MB / Pioneer DVR-108 / LiteOn LTR-52327S / Enermax 550W / HP P1100 21" CRT |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:48.





















