Newsgroup: it.comp.lang.visual-basic
Titolo: Perchè crasha? (un po' matematico e un po' difficile, credo)

Ciao a tutti amici!
Ho provato ad eseguire in maniera ricorsiva Root (una funzione che trova gli
zeri di un polinomio usando la "regula falsi", in maniera iterativa... in
pratica ho proceduto così; ho creato tre valori, due (A e B) ottenuti come
gli estremi dell'intervallo in cui mi interessa calcolare gli zeri (in
verità sono ottenuti come estremi dal teorema di gersgorin degli
autovalori...) e uno che inizialmente è uguale ad A che si sposta insieme
con A lungo la funzione. Quando si crea un intervallo tra A e il vettore di
supporto, ottenuto tramite incrementi di Tol, e A è positivo o uguale a zero
e B è negativo (o viceversa) allora viene calcolato lo zero dell'intervallo.
Alla fine si riporta il valore sinistro A sopra B e si ricomincia daccapo.
NB, il programma non calcola gli zeri del polinomio se l'intervallo
considerato ha estremi entrambi positivi o negativi.
SOLO CHE VA IN CRASH! SOB!
Avete una qualche idea del perchè? Io penso sia dovuto a Tol, se lo pongo
uguale a 0.5 per alcune situazioni semplici tutto funziona ok, ma va cmq in
crash per quelle più complesse
Se riuscite a scoprire il problema vincete la palma d'oro dell'analisi
numerica! ;-)
Private Sub Solve_Click()
Dim Val1 As Double
Dim Val2 As Double
Dim ValEnd As Double
Dim PolVal1 As Double
Dim PolVal2 As Double
Dim n As Long
Const Tol = 0.01 'valore piccolo in modo che non si salti a piè pari
            'uno zero
Val1 = AutovaloriMod.RestituisciA     'Il valore di inizio dell'intervallo
Val2 = Val1    'Un valore di supporto
ValEnd = AutovaloriMod.RestituisciB    'Il valore di fine intervallo
While (Val1 < ValEnd)     ' Fiunchè il valore iniziale non giunge ad essere
uguale a quello finale
PolinomioFrm.PolinomioX.Text = Val1    'Passa val1 al Textfield di
PolinomioFrm,
PolinomioFrm.Command2_Click    'simula la pressino del tasto,
PolVal1 = Val(Replace(PolinomioFrm.PolinomioY.Text, ",", "."))    'e calcola
il valore di y nel punto A d'inizio intervallo
PolinomioFrm.PolinomioX.Text = Val2    'Passa val2 al Textfield di
PolinomioFrm
PolinomioFrm.Command2_Click    'simula la pressione del tasto
PolVal2 = Val(Replace(PolinomioFrm.PolinomioY.Text, ",", "."))    'e calcola
il valore di y del valore di supporto
    If (PolVal1 > 0) And (PolVal2 > 0) Then    'Se A e B giacciono sull' Y
positivo
        While (PolVal2 >= 0) And (Val2 <> ValEnd)
        Val2 = Val2 + Tol    'Incrementa di Tol la x del valore di supporto
finchè la sua y non diventa negativa
        Wend
    ElseIf (PolVal1 < 0) And (PolVal2 < 0) Then    'Se A e B giacciono
sull'Y negativo
        While (PolVal2 <= 0) And (Val2 <> ValEnd)
        Val2 = Val2 + Tol    'Incrementa di Tol la x del valore di supporto
finchè la sua y non diventa positiva
        Wend
    ElseIf (PolVal1 = 0) And (PolVal2 = 0) Then
        Val2 = Val2 + Tol    'Se Il punto di inizio è uno zero, sposta di un
po' il vettore di supporto
    End If
    Label2.Caption = Label2.Caption & ModZeros.Root(Val1, Val2)     'Qui  A
e B segnano l'intervallo, calcola gli zeri in
                                                        'questo intervallo
    Val1 = Val2    'Porta A allo stesso valore di B e ricomincia.
Wend

Una risposta potrebbe essere data dalla ricorsività stessa. Infatti ad ogni
passaggio la sub deve salvare tutta una serie di parametri che dovrà
riprendere al termine della ricorsione. Se lo si fa un po' di volte la
memoria potrebbe esaurirsi.
Non sono sicuro, però!
CiaoZ
SebaMix
"Morpheus" <i@i.i> ha scritto nel messaggio
news:k9ib6.2004$ew1....@news.infostrada.it...


Non sono sicuro, però!
Ogni linguaggio ha un limite di chiamate a funzioni. Cioe' una
funzione chiama un'altra funzione, che ne chiama un'altra, che ne
chiama un'altra, ecc... piu' di n chiamate non le puoi fare perche'
esaurisci lo stack. Per VB mi sembrava 15, anche se potrei sbagliare.
Saluti.
-- 
      Gianni "bugbarbeq" Rondinini, 25, RA, 242, 152
  VBR - Vero Birro Romagnolo®, diffidate dalle imitazioni!
 Opel/ECC Calibrezio EVO-IV --- Kawasaki "Gas Gas" ZZ-R 1100
 ICQ# 36893168 - IRCNet: bugbarbeq, @ on #linux-it & #NetBSD

 ha scritto nel messaggio
news:lrnr6t81rprum5rke...@4ax.com...


chiamate! Grazie a entrambi e ciao!
Prego. Ma anziche' fare una cosa ricorsiva, perche' non fai una cosa
iterativa? Cosi' non hai chiamate a funzioni, che sono molto piu'
lente di un salto condizionato --cioe' un if...then--



[...]
La ricorsione sarebbe piů elegante, se il linguaggio di programmazione la
gestisse bene!
CiaoZ

 Saluti.
Private Function Try(v As Long, b As Long)
    Static n As Long
    n = n + 1
    Try v, b
End Function
Private Sub Form_Load()
    Try 1, 2
End Sub
?err.Description
Out of stack space
?n
 5219
Ciaotutti,
Alessandro

  5219
il mio
?n
5214
CiaoZ
SebaMix

 5219
Beh, ho sbagliato il limite di chiamate --chissa' dove mi sembrava di
averlo letto... boh...--, comunque il problema l'avevo identificato
bene :)
Saluti iterativi
-- 
      Gianni "bugbarbeq" Rondinini, 25, RA, 242, 152
  VBR - Vero Birro RomagnoloŽ, diffidate dalle imitazioni!


 zeri di un polinomio usando la "regula falsi", in maniera iterativa... in
Scusami ma non capisco perche' parli di ricorsione: nel pezzo di codice che hai
allegato, da nessuna parte (almeno mi sembra) la sub Solve richiama se stessa
ed asssumo che la Root sia quella originale del mio progetto Funzioni.
Il tuo problema, a mio avviso, sta' invece da un' altra parte.
Prendi il seguente pezzo di codice:
    If (PolVal1 > 0) And (PolVal2 > 0) Then 
        While (PolVal2 >= 0) And (Val2 <> ValEnd)
          Val2 = Val2 + Tol
        Wend
    ....
Nel loop While entri con, e.g., PolVal2 = 1;  ora, all' interno del loop,
incrementi solamente Val2 ma non aggiorni mai il valore di PolVal2.
Ma solo per un' incredibile botta di c..o capitera' di avere Val2 = ValEnd
ergo dal loop non uscirai mai: e tu di queste trappole ne hai messo ben due...
Prova a modificare il codice in questo modo:
Private Sub Solve_Click()
    Dim Val1 As Double
    Dim Val2 As Double
    Dim ValEnd As Double
    Dim PolVal1 As Double
    Dim PolVal2 As Double
    Dim N As Long
    Const Tol# = 0.001  ' valore piccolo in modo che non si salti a piè pari
                        ' uno zero
    Val1 = AutovaloriMod.RestituisciA      ' Il valore di inizio dell'intervallo
    'Val1 = 0   ' valore per la mia prova...
    Val2 = Val1 + Tol                      ' Un valore di supporto
    ValEnd = AutovaloriMod.RestituisciB    ' Il valore di fine intervallo
    'ValEnd = 10 ' come sopra.
 
    While (Val1 < ValEnd)                           ' Finchè il valore iniziale non giunge ad essere
                                                    ' uguale a quello finale
        PolVal1 = AitInt(X(), Y(), Val1)
        PolVal2 = AitInt(X(), Y(), Val2)
'
        If (PolVal1 > 0) And (PolVal2 > 0) Then     ' Se A e B giacciono sull' Y
                                                    ' positivo
            While (PolVal2 >= 0) And (Val2 < ValEnd)
                Val2 = Val2 + Tol                   ' Incrementa di Tol la x del valore di supporto
                                                    ' finchè la sua y non diventa negativa
                PolVal2 = AitInt(X(), Y(), Val2)    ' Aggiorna PolVal2.
            Wend
'
        ElseIf (PolVal1 < 0) And (PolVal2 < 0) Then ' Se A e B giacciono
                                                    ' sull 'Y negativo
            While (PolVal2 <= 0) And (Val2 < ValEnd)
                Val2 = Val2 + Tol                   ' Incrementa di Tol la x del valore di supporto
                                                    ' finchè la sua y non diventa positiva
                PolVal2 = AitInt(X(), Y(), Val2)
            Wend
'        
        ' Qui dovresti, invece, memorizzare il valore dello zero
        ' ed incrementare separatamente Val1 e/o Val2...
        ElseIf (PolVal1 = 0) And (PolVal2 = 0) Then
            Val2 = Val2 + Tol                       ' Se Il punto di inizio è uno zero, sposta di un
                                                    ' po' il vettore di supporto
        End If
'
        If PolVal1 * PolVal2 < 0 Then ' solo in questo caso Root funziona bene...
            txtPolRadici = txtPolRadici & Root(Val1, Val2) & vbCrLf
        End If
        Val1 = Val2    'Porta A allo stesso valore di B e ricomincia.
        Val2 = Val2 + Tol
'
         DoEvents ' sempre meglio averlo per poter uscire dal loop con un comando esterno.
   Wend
'
'
'
End Sub
e vedrai che molto rapidamente troverai le radici tra A e B e all' interno
del valore Tol di Root. BTW: la funzione AitInt e' quella che ti avevo inviato
e che richiama Aitken (valore di interpolazione).
Ciao e fammi sapere come va'.
Franco


omissis...