Dlaczego nie wychodzi z pętli?

0

Witam,

Mam taki kod i zastanawiam się, dlaczego zapętla się na amen:

Function funkcja(x As Double) As Double
    funkcja = (x * x) - 5
End Function

Private Sub CommandButton1_Click()

Dim a, b, dok, fa, fb, f0, x0, wb As Double

a = TextBox1.Text
b = TextBox2.Text
dok = TextBox3.Text

If Not IsNumeric(a) Or Not IsNumeric(b) Or Not IsNumeric(dok) Then
    MsgBox ("Podaj poprawne dane!")
    Else
        fa = funkcja(Val(a))
        fb = funkcja(Val(b))
        If (fa * fb) > 0 Then
            MsgBox ("Funkcja nie spełnia warunków!")
        Else
            Do While Abs(Val(a) - Val(b)) > Val(dok)
            x0 = ((Val(a) + Val(b)) / 2)
            f0 = funkcja(Val(x0))
            If Abs(Val(f0)) < Val(dok) Then
                MsgBox ("Poprawny koniec obliczeń!")
                TextBox4.Text = x0
                Exit Do
            End If
            If (fa * f0) < 0 Then
                b = x0
                Else
                    a = x0
                    fa = f0
            End If
            Loop
        End If
    End If

End Sub

Teoretycznie powinno wszystko grać, ale po podaniu danych i naciśnięciu przycisku Oblicz, program się wiesza.

EDIT: OK, znalazłem jedną (i pewnie nie ostatnią) z nieprawidłowości. Mianowicie po dojściu do sytuacji, gdzie do funkcji ma zostać przekazany argument o wartości 2,5 (wyliczony w drugim kroku pętli Do While, gdzie dane wejściowe to a = 0 i b = 10), tenże argument nie zostaje przekazany. Zostaje przekazany argument 2. Przy okazji poprawiłem kod, ale nadal nie zmienia to faktu, że nie działa to dobrze.

Reasumując:

x0 = ((Val(a) + Val(b)) / 2) ' tutaj przy drugim kroku wchodzą wartości 0 i 5, co daje po obliczeniach wartość zmiennej x0 = 2,5

f0 = funkcja(Val(x0)) ' tutaj powinien do funkcji zostać przekazany argument 2,5, a przekazuje się argument 2

0

Jeśli w pierwszym wyrażeniu zostaje do x0 przypisana wartość 2.5 (może z kropką, bo i tak są przecinki), a nigdzie indziej nie jest do niego nic przypisywane (szczególnie wartość 2), to nie ma możliwości, żeby ta zmienna miała wartość 2. Chyba że nie jest to zawsze 2.5 w pierwszym kroku? Jeśli oczywiście to jest Twój główny problem, tak zrozumiałem.

0

W pierwszym kroku do x0 = wpada 0 i 10, co daje 5 po obliczeniach i to 5 wpada jako argument do funkcji przy zmiennej f0. Następnie do x0 wpada 0 i 5, co daje 2.5 i to 2.5 jest ponownie przekazywane jako argument funkcji przy zmiennej f0, ale do samego ciała funkcji nie wpada 2.5 tylko 2...mogę pokazać na obrazach przy debugowaniu.

2

No więc tak. Nie znam się na VBA, ale patrząc do dokumentacji to metoda Val przyjmuje jako parametr string i konwertuje go na double i o tym za chwilę. Ale skoro x0 jest typu double i funkcja przyjmuje typ double to czy trzeba używać tam Val()?
Zamiast

			x0 = ((Val(a) + Val(b)) / 2)
            f0 = funkcja(Val(x0))

czy nie można tak

			x0 = ((Val(a) + Val(b)) / 2)
            f0 = funkcja(x0)

Jeżeli z jakiś powodów trzeba używać tego Val() no to x0 zostaje przekonwertowane na string, a że w Polsze separatorem dziesiętnym jest przecinek więc do Val zostaje przekazana taka wartość "2,5". No i w dokumentacji dla tego Val piszą "Val Zatrzymuje Konwertowanie pierwszego znaku, który nie może być interpretowany jako cyfra liczbowych, modyfikator liczbowych, liczbową znaków interpunkcyjnych lub biały znak." (tłumaczenie na polski - MS) stąd też zwraca Ci 2 bo przecinek mu nie pasuje. Wtedy trzeba ustalić format przekazywanego stringu. Jak to zrobić? Opis w dokumentacji (użyć Parse zamiast Val())
https://msdn.microsoft.com/pl-pl/library/9da280t0(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

0

@manuel.Artificer: Tak właśnie zrobiłem, ale jeszcze trzeba w tym przypadku zmienić deklarację funkcji:

Function funkcja(ByVal x As Double) As Double

Zamiast

Function funkcja(x As Double) As Double

Wtedy 2.5 przekazuje się prawidłowo, ale z kolei zaczynają dziać się inne rzeczy. Obcinają się wartości po przecinku w innych przypadkach, ale na 99% ma to związek właśnie z definicją, którą przytoczyłeś.

3
x0 = ((Val(a) + Val(b)) / 2)

Spróbuj to zmienić na:

x0 = ((CDbl(a) + CDbl(b)) / CDbl("2"))

I do funkcji przekazuj już oczywiście samo x0, a nie Val(x0).

0

@aurel: Dokładnie tak zrobiłem, pozmieniałem Val na CDbl i zagrało prawidłowo! Czułem, że coś jest na rzeczy przy konwersji typów, ale brakowało mi wiedzy. Dzięki Panie i Panowie za pomoc!

1 użytkowników online, w tym zalogowanych: 0, gości: 1