vbamania.pl
login:
hasło:
 
  *Rejestracja *Zapomniane hasło
 Dziś jest sobota, 18 maja 2024 roku.
Ustaw jako stronę startową Ulubione Napisz
PowrótPowrót do serwisu  RegulaminRegulamin rssRSS

  tytuł wątku:
Wątki dyskusji

całkowanie numeryczne metoda Simpsona


otwartyotwarty rozpoczął: th3rion postów: 25



napisał: Cyberek
postów: 11


umieszczony:
22 czerwca 2006
11:43

  
Wciąż mam problem.
y=(2/pi)*calka_od_zera_do_nieskonczonosci[(x*Z''(x)-w*Z''(w))/(x^2-w^2) dx]

Sposób w jaki to liczę:
Function rr_r(input_col As Range, output_col As Range, Zjw As Double, w As Double) As Double
   Dim delta As Double, x As Double, wyraz As Double, i As Integer, Zjx As Double, Zjxa As Double, Zjxb As Double, calka As Double, a As Double, b As Double, n As Integer
   Const Pi As Double = 3.14159265358979
   a = 0#
   b = 1000000000#
   n = 1000
   rr_r = 0#
   calka = 0#
   delta = (b - a) / n
   x = a
   For i = 1 To n Step 2
   Zjx = cubic_spline(input_col, output_col, x)
   Zjxa = cubic_spline(input_col, output_col, x + delta)
   Zjxb = cubic_spline(input_col, output_col, x + 2 * delta)
   wyraz = yr(Zjw, Zjx, w, x) + 4 * yr(Zjw, Zjxa, w, x + delta) + yr(Zjw, Zjxb, w, x + 2 * delta)
   calka = calka + wyraz
   x = x + 2 * delta
   Next i
   rr_r = ((2 / Pi) * calka) * delta / 3
End Function

Function yr(Zjw As Double, Zjx As Double, w As Double, x As Double) As Double
   yr = (x * Zjx - w * Zjw) / (x ^ 2 - w ^ 2)
End Function



Moje pytanie brzmi: czy gdzieś w tym kodzie jest błąd.
Wyjaśnienie symboli:
x - zmienna po któej całkujemy,
w - częstotliwość brana z serii pomiarowej
Z''(x) - wartosc urojona impedancji zespolonej dla punktu x wyliczana metodą interpolacji: Cublic Spline (funkcja rowniez napisana w VBA - dziala prawidlowo)
Z''(w) - wartosc urojona impedancji zespolonej dla czestotliwosci w (z serii pomiarowej)

Odnocze wrazenie, iz gdzies popelnilem banalny blad gdyz wartosci wynikowe troszke roznia sie od tych, jakich oczekuje.
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
19:19

  
Ok. Wlasnie brakowalo mi wiedzy jak bezposrednio zdebugowac dzialanie wszystkich funkcji.

Rozumiem ze sugerujesz ze gdzies pomylilem sie przy definicji funkcji. Pozniej jeszcze raz ja przejze (ale jesli chodzi Ci o to ze brakuje 2/pi oraz const na koncu - to beda one dodane juz w arkuszu gdyz nie znajduja sie one "pod całką")
napisał: admin
postów: 613


umieszczony:
18 czerwca 2006
19:07

  
Wstaw do któregokolwiek modułu kod:

Sub Wypisz()
   MsgBox rr_r(0.1, 1000000, 1000, Range("B2:B63"), Range("D2:D63"), -43.631, 0.1)
End Sub



Jeśli uruchomisz tę funkcję w edytorze VBA to zobaczysz, że przyczyną błędu jest dzielenie przez 0 w funkcji yr.
Musisz zabezpieczyć tę funkcję przed wystapieniem tego błędu.

I taka uwaga natury ogólnej...
Pamiętaj, ze poprawne wyniki otrzymasz tylko wówczas, gdy funkcje będą napisane poprawnie, to znaczy będą realizowały założony przez Ciebie algorytm.

Powodzenia:)
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
15:53

  
Update.2

Zmienilem funkcje na:
Function rr_r(a As Double, b As Double, n As Integer, input_col As Range, output_col As Range, Zjw As Double, w As Double) As Double
   Dim delta As Double, x As Double, wyraz As Double, i As Integer, Zjx As Double, calka As Double
   rr_r = 0#
   calka = 0#
   delta = (b - a) / n
   x = a
   For i = 1 To n Step 2
   Zjx = cubic_spline(input_col, output_col, x)
   wyraz = yr(Zjw, Zjx, w, x) + 4 * yr(Zjw, Zjx, w, x + delta) + yr(Zjw, Zjx, w, x + 2 * delta)
   calka = calka + wyraz
   x = x + 2 * delta
   Next i
   rr_r = calka * delta / 3
End Function



Poprawiłem też w funkcji cubic_spline wartosc wejsciowa x z Range na Double by nie miec problemu z zgodnoscia typow. Teraz dostaje tylko blad:
#ARG!.

Aktualna wersja:
http://redrose.lap.pl/kk-transformata4.xls
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
15:32

  
Update.1

Błąd nazwy zaistaniał w wyniku nazwania modułu tak samo jak funkcji wewnątrz.
Poprawiony xls pod adresem:
http://redrose.lap.pl/kk-transformata3.xls

Teraz już nie jest błędem nazwa funkcji a właśnie rekurencja.
Czy ktoś może pomóc z problemem zasugerowanym przez admina w Uwadze trzeciej?
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
15:17

  
Wywołanie funkcji faktycznie było złe w arkuszu, poprawiłem ale to i tak kończe z tym samym błędem #NAZWA?
Błędne działanie funkcji yr również poprawiłem.

Natomiast nie rozumiem w czym tkwi problem z rekurencją. W wcześniejszych przykładach była ona wykonywana dokładnie w ten sam sposób:
tutaj kod z postu Rycha data: 06.06.2006 01:01:01:
Function Integral(F As String, a As Double, b As Double, n As Integer) As Double
   Dim delta As Double, x As Double, wyraz As Double, i As Integer
   Integral = 0#
   delta = (b - a) / n
   x = a
   For i = 1 To n Step 2
   wyraz = y(F, x) + 4 * y(F, x + delta) + y(F, x + 2 * delta)
   Integral = Integral + wyraz
   x = x + 2 * delta
   Next i
   Integral = Integral * delta / 3
End Function


Wygląda na to, iż w tym kodzie jest popełniany dokładnie ten sam błąd (rekurencja bez parametrów).

Niestety nie jestem zbyt biegły w VBA i jedyne co mogę zrobić to przeanalizować jakiś podobny kod do problemu który potrzebuję rozwiązać i zmodyfikować go do swoich potrzeb. Niestety tutaj nadal jestem w polu ;).

Adres do poprawionego arkusza:
http://redrose.lap.pl/kk-transformata2.xls

Mam nadzieje ze w niedlugim czasie z Wasza pomoca bede w stanie zrozumiec gdzie nadal tkwi błąd.
napisał: admin
postów: 613


umieszczony:
18 czerwca 2006
13:50

  
Cytat:

Oj znielubicie mnie za pisanie zbyt często. Otóż trochę powalczyłem i nic mi nie wyszło.

Nie, wręcz przeciwnie:)

Wywołujesz funkcję tak:

=rreal(J2;J3;J1;B2:B63;D2:D63;D2;B2)

Niestety w projekcie VBA zwiazanym z tym arkuszem nie ma takiej funkcji.
Jest za to funcja rr_r. Powinieś napisać ww. formułę tak:

=rr_r(J2;J3;J1;B2:B63;D2:D63;D2;B2)

Uwaga trzecia:

Wiesz co robisz używając rekurencji w kodzie tej funkcji?

Function rr_r(a As Double, b As Double, n As Integer, input_col As Range, output_col As Range, Zjw As Double, w As Double) As Double
   Dim delta As Double, x As Double, wyraz As Double, i As Integer
   rr_r = 0#
   delta = (b - a) / n
   x = a
   For i = 1 To n Step 2
   Zjx = cubic_spline(input_col, output_col, x)
   wyraz = yr(Zjw, Zjx, w, x) + 4 * yr(Zjw, Zjx, w, x + delta) + yr(Zjw, Zjx, w, x + 2 * delta)
   'w poniższej linii masz wywołanie rekurencyjne funkcji rr_r, ale ono
   'nie zadziała, bo nie podałeś argumentów dla funcji rr_r!!!!!
   rr_r = rr_r + wyraz
   x = x + 2 * delta
   Next i
   'w poniższej linii masz wywołanie rekurencyjne funkcji rr_r, ale ono
   'nie zadziała, bo nie podałeś argumentów dla funcji rr_r!!!!!
   rr_r = rr_r * delta / 3
End Function



Trzeci błąd:

Funkcja rr_r wykorystuje funkcję yr.
Oto kod tej funkcji:

Function yr(Zjw As Double, Zjx As Double, w As Double, x As Double) As Double
   y = (x * Zjx - w * Zjw) / (x ^ 2 - w ^ 2)
End Function



Niestety to nie bedzie działać, bo nie ma tutaj zwracania wartości funkcji.
Może tak:
Function yr(Zjw As Double, Zjx As Double, w As Double, x As Double) As Double
   yr = (x * Zjx - w * Zjw) / (x ^ 2 - w ^ 2)
End Function

napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
13:14

  
Update2.

Oj znielubicie mnie za pisanie zbyt często. Otóż trochę powalczyłem i nic mi nie wyszło.

Napisałem funkcje:
Function yr(Zjw As Double, Zjx As Double, w As Double, x As Double) As Double
   y = (x * Zjx - w * Zjw) / (x ^ 2 - w ^ 2)
End Function

Function rr_r(a As Double, b As Double, n As Integer, input_col As Range, output_col As Range, Zjw As Double, w As Double) As Double
   Dim delta As Double, x As Double, wyraz As Double, i As Integer
   rr_r = 0#
   delta = (b - a) / n
   x = a
   For i = 1 To n Step 2
   Zjx = cubic_spline(input_col, output_col, x)
   wyraz = yr(Zjw, Zjx, w, x) + 4 * yr(Zjw, Zjx, w, x + delta) + yr(Zjw, Zjx, w, x + 2 * delta)
   rr_r = rr_r + wyraz
   x = x + 2 * delta
   Next i
   rr_r = rr_r * delta / 3
End Function



do jej wywolania podaje: dolny zakres calkowania, gorny zakres calkowania, liczbe krokow, serie x'ow dla funkcji cubic_spline, serie y'kow dla funkcji cubic spline, wartosc impedancji urojonej w czestotliwosci dla ktorej licze wartosc rzeczywista, wartosc owej czestotliwosci

Niestety dostaje blad #NAZWA? przy probie zastosowania w/w funkcji w arkuszu.

Ponizej link do arkusza demonstrujacego problem:
http://redrose.lap.pl/kk-transformata.xls

Pozdrawiam i przepraszam za spamiemienie... ale problem musze rozwiazac na dniach.
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
12:13

  
Update. Wklejony nize jkod funkcji cubic_spline dziala gdy dane sa posortowane rosnaco.
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
01:41

  
Ps. Przetestowałem poniższy kod funkcji Spline i niestety wylicza on błędne wartości. Zatem jedyną możliwością obliczenia tej funkcji jest zastosowanie wcześniej wspomnianego plugina dostępnego pod adresem:
http://www.xlxtrfun.com/XlXtrFun/XlXtrFun.htm
lub bezpośrednio:
http://redrose.lap.pl/XlXtrFun.xll

Opis instalacji:
http://www.xlxtrfun.com/XlXtrFun/ReadMeXlXtrFunAndSurfGen.htm


W związku z tym iż nie mam działającego kodu tej funkcji dla VBA czy jest możliwe wogóle stosowanie w VBA takich "rozszerzeń"?
napisał: Cyberek
postów: 11


umieszczony:
18 czerwca 2006
01:24

  
Chciałbym trochę rozwinąć problem.

Mam serię danych X oraz Y będących wynikami pomiaru.
Dla tej serii danych wykonuję funkcję dostępną w postaci pluginu (plik .xll): Cubic Spline. Funkcja ta jest wywolywana:
Spline(A,B,C,D,E), gdzie A i B okresla zakres danych X'ów; C,D - zkres Yków, E - dowolny (z zakresu A,B) X dla ktorego funkcja oblicza Y.
(Na końcu zamieszczam znaleziony kod tej funkcji w postaci VBA)

Wykonaniue funkcji Spline jest niezbędne do całkowania po dowolnych wartościach (dowolnym zakresie/dowolnych x'ach) nastepujacych funkcji:

A=[(2/PI)*calka_w_zakresie( (x*Z''(x)-w*Z''(w)) / (x^2-w^2) dx]+stala
B=-(2*w/PI)*calka_w_zakresie( (Z'(x)-Z'(w) / (x^2-w^2) )dx

Przy czym:
- zakres calkowania determinuje jakie otrzymamy x'y (dla ktorych wyliczamy odpowiednie wartosci opisane ponizej przy pomocy Spline)

- Z'(x) (oraz Z''(x)) jest wartoscia otrzymana z funkcji Spline dla danego x'a
- Z'(w) (oraz Z'' (w)) jest wartością w danym punkcie w z początkowej serii danych (z których później obliczany wartosci Z' i Z'' dla dowolnego (a nie tylko danego z pomiarow) punktu x).

- stala = dana liczba wprowadzana do funkcji z arkusza

Funkcje podcalkowe nie ulegaja zmianie, zatem moga byc zaimplementowane wewnatrz modulu VBA.


Czy zgodnie z powyższymi danymi któryś z programistów VBA mógłby zmodyfikować dla mnie powyższy kod całkowania metodą simpsona?


Pozdrawiam i z góry dziękuję za pomoc.


Wspomniana powyzej kod VBA funkcji Spline:

'******************** Cubic_Spline by SRS1 Software ****************
'
'
' Version 1.01


Function cubic_spline(input_column As Range, _
                      output_column As Range, _
                      x As Range)

'Purpose: Given a data set consisting of a list of x values
' and y values, this function will smoothly interpolate
' a resulting output (y) value from a given input (x) value


' This counts how many points are in "input" and "output" set of data
Dim input_count As Integer
Dim output_count As Integer

input_count = input_column.Rows.Count
output_count = output_column.Rows.Count

' Next check to be sure that "input" # points = "output" # points
If input_count <> output_count Then
    cubic_spline = "Something's messed up! The number of indeces number of output_columnues don't match!"
    GoTo out
End If
 
ReDim xin(input_count) As Single
ReDim yin(input_count) As Single

Dim c As Integer

For c = 1 To input_count
xin(c) = input_column(c)
yin(c) = output_column(c)
Next c

'''''''''''''''''''''''''''''''''''''''
' values are populated
'''''''''''''''''''''''''''''''''''''''
Dim n As Integer 'n=input_count
Dim i, k As Integer 'these are loop counting integers
Dim p, qn, sig, un As Single
ReDim u(input_count - 1) As Single
ReDim yt(input_count) As Single 'these are the 2nd deriv values

n = input_count
yt(1) = 0
u(1) = 0

For i = 2 To n - 1
    sig = (xin(i) - xin(i - 1)) / (xin(i + 1) - xin(i - 1))
    p = sig * yt(i - 1) + 2
    yt(i) = (sig - 1) / p
    u(i) = (yin(i + 1) - yin(i)) / (xin(i + 1) - xin(i)) - (yin(i) - yin(i - 1)) / (xin(i) - xin(i - 1))
    u(i) = (6 * u(i) / (xin(i + 1) - xin(i - 1)) - sig * u(i - 1)) / p
    
    Next i
    
qn = 0
un = 0

yt(n) = (un - qn * u(n - 1)) / (qn * yt(n - 1) + 1)

For k = n - 1 To 1 Step -1
    yt(k) = yt(k) * yt(k + 1) + u(k)
Next k


''''''''''''''''''''
'now eval spline at one point
'''''''''''''''''''''
Dim klo, khi As Integer
Dim h, b, a As Single

' first find correct interval
klo = 1
khi = n
Do
k = khi - klo
If xin(k) > x Then
khi = k
Else
klo = k
End If
k = khi - klo
Loop While k > 1
h = xin(khi) - xin(klo)
a = (xin(khi) - x) / h
b = (x - xin(klo)) / h
y = a * yin(klo) + b * yin(khi) + ((a ^ 3 - a) * yt(klo) + (b ^ 3 - b) * yt(khi)) * (h ^ 2) / 6


cubic_spline = y

out:
End Function

napisał: Rycho
postów: 291


umieszczony:
7 czerwca 2006
01:13

  
Sub test()
  Dim w As Double, w1 As Double

  w = y1("x*y", 2, 3)
  
  w = Cos(0.5) * Exp(0.7)
  w1 = y1("cos(x)*exp(y)", 0.5, 0.7)
End Sub

Function y1(funkcja As String, x As Double, y As Double) As Double
  Dim xF As String
  
  If InStr(1, funkcja, "exp") > 0 Then
    xF = Replace(funkcja, "exp", "egze_begze")
    xF = Replace(Replace(xF, "x", _
          Replace(x, ",", ".")), "y", Replace(y, ",", "."))
    y1 = Evaluate(Replace(xF, "egze_begze", "exp"))
  Else
    y1 = Evaluate(Replace(Replace(funkcja, "x", _
          Replace(x, ",", ".")), "y", Replace(y, ",", ".")))
  End If
End Function

napisał: th3rion
postów: 6


umieszczony:
6 czerwca 2006
14:15

  
A dajmy na to jesli chcialbym zrozniczkowac funkcje? Nie chodzi mi o to jak napisac kod do rozniczkowania tylko, jak sie zmieni kod do zamiany funkcji dla 2 zmiennych, na przyklad dla funkcji y'=x*y
napisał: th3rion
postów: 6


umieszczony:
6 czerwca 2006
07:53

  
Bardzo dziekuje za pomoc. Artik i Rycho
napisał: Rycho
postów: 291


umieszczony:
6 czerwca 2006
01:01

  
Hej.
Odrobinę bym to zmienił.
Kod do modułu:
Function y(funkcja As String, x As Double) As Double
  Dim xF As String
  If InStr(1, funkcja, "exp") > 0 Then
    xF = Replace(funkcja, "exp", "egze_begze")
    xF = Replace(xF, "x", Replace(x, ",", "."))
    xF = Replace(xF, "egze_begze", "exp")
    y = Evaluate(xF)
  Else
    y = Evaluate(Replace(funkcja, "x", Replace(x, ",", ".")))
  End If
End Function

Function Integral(F As String, a As Double, b As Double, n As Integer) As Double
  Dim delta As Double, x As Double, wyraz As Double, i As Integer
  Integral = 0#
  delta = (b - a) / n
  x = a
  For i = 1 To n Step 2
  wyraz = y(F, x) + 4 * y(F, x + delta) + y(F, x + 2 * delta)
  Integral = Integral + wyraz
  x = x + 2 * delta
  Next i
  Integral = Integral * delta / 3
End Function



Wykorzystanie w VBA:
Sub test()
  Dim a As Double, pole As Double, P1 As Double
  P1 = WorksheetFunction.pi()
  'wartość funkcji dla Pi
  a = y("x*SIN(x)", P1)
  'pole powierzchni
  pole = Integral("x*sin(x)", 0, P1, 100)
End Sub



Wykorzystanie bezpośrednio w arkuszu jako funkcji użytkownika:
A1 x*sin(x)
A2 0
A3 =PI()
A4 100
A5 =Integral(A1;A2;A3;A4)

lub
=Integral("x*sin(x)";0;Pi();100)


Rycho
napisał: th3rion
postów: 6


umieszczony:
5 czerwca 2006
23:54

  
Hmm ja sie dopiero ucze i nie bardzo wiem jak to poskladac wszystko do kupy, to co napisal Rycho, zeby to dzialalo. Chcialbym wiedziec bo moze sie kiedys przyda :/
napisał: Rycho
postów: 291


umieszczony:
5 czerwca 2006
23:20

  
Witaj.
To nie tak :) Wpukanie tego kodu to faktycznie kilkanaście sekund ale siedziałem nad nim z półtorej godziny. :(

Jeszcze poprawka bo dla podstawowej funcji ten kod nie działa.
Function y(funkcja As String, x As Double) As Double
  Dim xF As String
  If InStr(1, funkcja, "exp") > 0 Then
    xF = Replace(funkcja, "exp", "egze_begze")
    xF = Replace(xF, "x", Replace(x, ",", "."))
    xF = Replace(xF, "egze_begze", "exp")
    y = Evaluate(xF)
  Else
    y = Evaluate(Replace(funkcja, "x", Replace(x, ",", ".")))
  End If
End Function

napisał: Rycho
postów: 291


umieszczony:
5 czerwca 2006
01:54

  
Witam.
Też mnie to męczyło i wykombinowalem coś takiego:
Sub test()
  Dim a As Double
  a = y("x*SIN(x)", 1.43)
End Sub

Function y(funkcja As String, x As Double) As Double
  y = Evaluate(Replace(funkcja, "x", Replace(x, ",", ".")))
End Function

napisał: th3rion
postów: 6


umieszczony:
4 czerwca 2006
23:48

  
Heh dziala wspaniale o to chodzilo. Dziekuje bardzo. Zeby tylko antywir nie szalal przy zapisywaniu byloby wogole wspaniale :) ale to juz mniejsza z tym.
napisał: th3rion
postów: 6


umieszczony:
31 maja 2006
00:48

  
Nie da sie tego zrobic za pomoca Cell lub Value. Prawde mowiac nie wiem jak sie do tego zabrac. Prosze o pomoc.


<-wstecz  1 2  dalej->
wszystkich stron: 2


Sortuj posty: z