Pierwsza sprawa to typy danych parametrów procedury i kilka linijek niżej ich:
Procedure Scraton(f, x, y, xe, eps, hmin);
value xe, eps, hmin;
real x, y, xe, eps, hmin;
label etb;
real function f;
Begin
real E, k1, k2, k3, k4, k5 as real;
boolean fi;
Domyślam się, że x
, y
, xe
, eps
i hmin
to mają być parametry typu real
, etb
to etykieta, a f
to funkcja przekazywana do procedury Scraton
. Są też zmienne lokalne E
, k1
, k2
, k3
, k4
, k5
typu real
oraz jedna fi
typu logicznego.
O ile z deklaracją paramtrów i zmiennych lokalnych nie widzę problemu, to jaka ma być początkowa wartość zmiennej fi
? Prawda czy fałsz? Bo ta jest używana w warunku zaraz pod jej deklaracją (pomijając tekst w nawiasach, który pewnie jest komentarzem). Obstawiam, że False
.
Nie wiem też czy zmiany przeprowadzane na parametrach wejściowych mają mieć globalny zasięg. To co prawda sugeruje sekcja pod etykietą c
, ale tego nie jestem pewien.
Wstępna wersja wygląda tak:
uses
Math;
var
h: real;
type
TRealFunction = function(x, y: real): real;
procedure Scraton(f: TRealFunction; x, y, xe, eps, hmin: real);
var
E, k1, k2, k3, k4, k5: real;
fi: boolean = false;
label
a, b, c;
begin
if fi then
a: begin
E := abs((xe - x) / h);
if E <= 1.5 then fi := E > 1 else goto b;
end;
if fi then h := 0.5 * (xe - x) else h := xe - x;
b: k1 := h * f(x, y);
k2 := h * f(x + 0.222222222222 * h, y + 0.2222222222222 * k1);
k3 := h * f(x + 0.333333333333 * h, y + 0.8333333333333 * k1 + 0.25 * k2);
k4 := h * f(x + 0.75 * h, y + 0.5390625 * k1 - 1.8984375 * k2 + 2.109375 * k3);
k5 := h * f(x + 0.9 * h, y - 0.3105 * k1 + 1.8225 * k2 - 1.1016 * k3 + 0.4896 * k4);
E := (0.34 * k1 - 0.972 * k2 + 1.632 * k4 - k5) * (0.129357298475 * k1 - 0.551470588235 * k2
+ 0.46568627451 * k3 - 0.0435729847494 * k4) / (k4 - k1);
k2 := abs(E);
if k2 > eps then goto c;
y := y - E + 0.104938271605 * k1 + 0.476470588235 * k3 + 0.237037037037 * k4 + 0.181554103123 * k5;
if fi then
begin
x := x + h;
c: h := h * (eps / k2) ** 0.2;
if abs(h) > hmin then goto a else exit;
end;
x := xe;
fi := true;
end;
Kod kompiluje się bez żadnych problemów czy ostrzeżeń. W sumie to niewiele rzeczy trzeba było poprawić, bo składniowo nawet pasował. Nie zmieniałem wielkości liter w identyfikatorach, żeby był podobny do oryginału. Musisz sobie sprawdzić poprawność jej działania. Jednak zastosowałem dwa uproszczenia – o tym niżej.
Nigdzie nie widzę deklaracji h
– nie jest to ani zmienna lokalna, ani też parametr. Dlatego zadeklarowałem ją jako zmienną globalną. Jej wartość najpierw ustalana jest w drugim warunku, a następnie używana jest do obliczania wartości dla zmiennych k*
, więc nie trzeba jej inicjalizować.
Druga sprawa – etykieta etb
nie znajduje się wewnątrz procedury Scraton
. Każda lokalnie zadeklarowana etykieta musi być lokalnie użyta, nie może się znajdować w innej procedurze. Dlatego zamieniłem odwołanie się do niej na instrukcję exit
, aby w tym miejscu przerwać działanie procedury, bo obstawiam, że tak ma to działać.
No i w Pascalu operator ^
służy do wydłubywania danych spod wskaźnika, więc trzeba było go wymienić. Free Pascal do potęgowania przewiduje operator **
i z tego też skorzystałem. Mam nadzieję, że w tym miejscu faktycznie o potęgowanie chodziło.