Visualizzazione dei risultati da 1 a 8 su 8
  1. #1

    Imprecisione mostruosa su VB

    Ciao a tutti, ho sviluppato un piccolo programmino per il calcolo dell'integrale definito di una funzione in VB.NET.
    Il mio problema è l'estrema imprecisione con cui VB e qualsiasi altro linguaggio di programmazione con cui ho provato (Java, ActionScript, PHP, C), nella somma di due numeri; uno int e l'altro double.
    Il codice è il seguente:
    Codice PHP:
        Private Sub rettangoli()
            
    txtresult.Text += "<RISULTATI tipo='rettangoli'>"
            
    If Not (IsNumeric(TextBox1.Text)) Or Not (IsNumeric(TextBox2.Text)) Or Not (IsNumeric(TextBox3.Text)) Then
                txtresult
    .Text += "ERRORE: TIPO DATI ERRATI"
                
    GoTo exith
            End 
    If
            
    Dim a As Integer CInt(TextBox1.Text)
            
    Dim b As Integer CInt(TextBox2.Text)
            
    Dim n As Integer CInt(TextBox3.Text)
            
    Dim h As Double
            h 
    = (a) / n
            Dim ss 
    As Double 0
            Dim xi 
    As Double a
            
    Do While xi <= (h)
                
    ss ss * (/ (+ (xi xi)))
                
    xi xi h
                txtresult
    .Text += ("<XI>" xi "</XI>" " <SS>" ss "</SS>" "<H> " "</H>")
                
    Debug.Print(ss)
            
    Loop
            Dim sd 
    As Double 0
            xi 
    h
            
    Do While (xi b)
                
    sd sd * (/ (+ (xi xi)))
                
    xi xi h
            Loop
            Dim hint 
    As Double = (ss sd) / 2
            Dim err 
    As Double ss sd
    exith
    :
            
    txtresult.Text += "<RESULT>" hint " " err "</RESULT></RISULTATI>"
        
    End Sub 
    L'output di questo programma mostra, con n = 100, alla 80° iterazione è :
    Codice PHP:
    [...]
      <
    SS>2,65725035665318</SS
      <
    H>0,01</H
      <
    XI>0,79</XI
      <
    SS>2,682119792117</SS
      <
    H>0,01</H
      <
    XI>0,8</XI
      <
    SS>2,70674881742332</SS
      <
    H>0,01</H
      <
    XI>0,810000000000001</XI
      <
    SS>2,73113906132576</SS
      <
    H>0,01</H
      <
    XI>0,820000000000001</XI
      <
    SS>2,75529219217535</SS
      <
    H>0,01</H
      <
    XI>0,830000000000001</XI
      <
    SS>2,77920991520811</SS
      <
    H>0,01</H
      <
    XI>0,840000000000001</XI
      <
    SS>2,80289396991828</SS
      <
    H>0,01</H
      <
    XI>0,850000000000001</XI
      <
    SS>2,82634612751678</SS
      <
    H>0,01</H
      <
    XI>0,860000000000001</XI
      <
    SS>2,84956818847469</SS
      <
    H>0,01</H
    [...] 
    Ora, a casa mia 0,8 + 0,01 = 0,81 e non 0,810000000000001.
    Da cosa può essere causato questo errore?

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480

    Re: Imprecisione mostruosa su VB

    Floating Point
    http://en.wikipedia.org/wiki/Floating_point

    Leggi da ...

    Accuracy problems

    ...

    For example, the non-representability of 0.1 and 0.01 (in binary) ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    L'avevo immaginato Non si può correggere allora...che palle!
    Io che pensavo d'aver fatto qualcosa di bello e preciso.
    Grazie comunque

    Una curiosità: in questo programma la funzione di cui calcolo l'integrale è (4 / (1 + (xi * xi)).
    Se io volessi fare in modo di generalizzare il tutto e farla inserire manualmente come potrei fare? Ho provato ad utilizzare il codice che si trova su msdn per la funzione Eval() ma ho ancora qualche ostacolo logico.

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Originariamente inviato da KaNnA
    ... msdn per la funzione Eval() ma ho ancora qualche ostacolo logico.
    Quale ostacolo?

    Oppure, ti devi costruire tu un "parser di espressioni" ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Dunque, la funzione che ho scaricato da msdn è questa:
    Codice PHP:
    Public Function Evaluate(ByVal syntax As String) As Object
            
    'Creo il compilatore VB e relativi paramentri
            Dim provider As New Microsoft.VisualBasic.VBCodeProvider()
            Dim param As New CompilerParameters()
            param.GenerateInMemory = True
            param.GenerateExecutable = False
            param.ReferencedAssemblies.Add("System.dll")

            '
    Creo una classe temporanea
            Dim src 
    As String "Imports System" ControlChars.Cr _
            
    "Class Evaluator" ControlChars.Cr _
            
    "Public Function Eval() As Object" ControlChars.Cr _
            
    "Return " syntax ControlChars.Cr _
            
    "End Function" ControlChars.Cr _
            
    "End Class"

            'Compilo dinamicamente la classe
            Dim results As CompilerResults = provider.CompileAssemblyFromSource(param, src)
            If results.Errors.Count > 0 Then
                Throw New ArgumentException("Parametro non valido.", "syntax")
            Else
                '
    Creo istanza della classe Evaluator e invoco metodo Eval()
                
    Dim o As Object results.CompiledAssembly.CreateInstance("Evaluator")
                
    Dim method As MethodInfo o.GetType().GetMethod("Eval")
                Return 
    method.Invoke(oNothing)
            
    End If
        
    End Function 
    Ora, se non leggo male, questa crea una classe runtime che contiene il metodo Eval(), il quale ritorna il valore numerico dell'espressione passata.
    Io dovrei fare in modo da generalizzare il tutto.
    Esempio:
    hint = h * f(a)
    con f(x) = 1/x

    Quindi dovrei andare a sostituire le x nella funzione con il valore che assume a.
    replace potrebbe fare al caso mio?
    Buttando giù qualcosa velocemente, ho fatto così:
    Codice PHP:
        Public Function PreEval(ByVal a) As String
            Dim strCont 
    As String
            strCont 
    TextBox4.Text.Replace("x"a)
            Return 
    strCont
        End 
    Function 
    Il problema è che continua a ritornarmi Parametro non valido, anche se provo semplicemente a fare Evaluate("1/0,1") o Evaluate("1/(0,1)")
    Non gestisce i decimali?

  6. #6
    Usa il punto decimale e non la virgola, esattamente come faresti in un sorgente VB. In ogni caso se devi semplicemente fare dei calcoli (e non generare altro codice al volo) è molto più efficiente e sensato usare un parser di espressioni (come questo).
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Grazie mille, ora è tutto funzionante!
    E grazie anche per il link, è stato molto utile!

  8. #8
    Di niente, ciao!
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.