Skocz do zawartości
Forum komputerowe PC Centre
_Mithrandir

metoda wyznaczników w Turbo Pascalu

Rekomendowane odpowiedzi

Witam... mam problem z programem w TP, ma on rozwiązywać układ dwóch równań z dwoma niewiadomymi metodą wyznaczników z uwzględnieniem równania nieoznaczonego i sprzecznego. Napisałem ten program, ale wynik sprawdza się dla niewielu przypadków... z tego co wiem, to metoda ta działa tak, że jeśli mam dwa równania ax+by=c i dx+ey=f (program pyta o a,b,c,d,e,f), to Wg=a*e-d*b, Wx=c*e-f*b, Wy=a*f-d*c. x=Wx/Wg, y=Wy/Wg dla Wg<>0, dla Wg=Wx=Wy=0 układ jest nieoznaczony, a dla W=0 ^ (Wx<>0 v Wy<>0) układ jest sprzeczny. Mogę podesłać plik z kodem w formacie PAS, bo nie mam pojęcia co mogłem zrobić nie tak.

 

Niby program dobrze robi obliczenia, ale czasem po podstawieniu x i y do równań po prostu wychodzi zły wynik, a i przy metodzie podstawiania inne rozwiązanie układu wychodzi (wychodzi w zasadzie tylko dla jakichś prostych liczb, jak zaczynam majstrować z dużymi i małymi liczbami naraz, albo ujemne i niecałkowite to zaraz są kosmiczne wyniki).

Edytowane przez _Mithrandir

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Podrzuć kod (wklej go na forum). Wzory masz dobre. Najpewniej jest to błąd w kodzie...

 

z drugiej strony rozwiązywanie równań metoda wyznaczników jest "niestabilne numerycznie" tzn., że wyniki niezawsze są dobre.

 

Mała uwaga: Zamiast Wx = 0, Wy = 0 powinieneś sprawdzać czy Wx i Wy nie są bliskie zera. np. czy (Wx > -0.0000001) AND (Wx < 0.0000001), Tak samo dla Wg. Obliczenia na komputerze są opatrzone błędem bo nie każdą liczbę da się przedstawić w maszynie (np. 1/3 nie da się dokładnie zapisać w postaci binarnej) dlatego porównywanie z 0 niezawsze zadziała (bo np. po odejmowaniu liczba będzie bliska ale różna od zera).

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

program wyznaczniki;

uses crt;

var

i:integer;

a,b,c,d,e,f,wg,wx,wy,x,y:real;

 

begin

 

clrscr;

for i:=1 to 80 do

begin

delay(1);

write('_');

end;

writeln;

 

writeln ('PIERWSZE ROWNANIE: ax+by=c');

writeln;

write ('-podaj czynnik a: ');

readln ( a );

write ('-podaj czynnik b: ');

readln ( b );

write ('-podaj czynnik c: ');

readln ( c );

for i:=1 to 80 do

begin

delay(1);

write('_');

end;

writeln;

 

writeln ('DRUGIE ROWNANIE: dx+ey=f');

writeln;

write ('-podaj czynnik d: ');

readln ( d );

write ('-podaj czynnik e: ');

readln ( e );

write ('-podaj czynnik f: ');

readln ( f );

for i:=1 to 80 do

begin

delay(1);

write('_');

end;

writeln;

 

writeln ('UKLAD ROWNAN:');

writeln;

writeln (a:0:2,'x+',b:0:2,'y=',c:0:2,' ^ ',d:0:2,'x+',e:0:2,'y=',f:0:2);

for i:=1 to 80 do

begin

delay(1);

write('_');

end;

writeln;

 

wg:=(a*e)-(d*b );

wx:=(c*e)-(f*b );

wy:=(a*f)-(d*c );

 

if (wg=0) and (wx=0) and (wy=0) then

writeln ('Uklad nieoznaczony. ');

if (wg=0) then

if (wx<>0) or (wy<>0) then

writeln ('Uklad sprzeczny. ');

if wg<>0 then

begin

x:=wx/wg;

y:=wy/wg;

writeln ('ROZWIAZANIE:');

writeln;

writeln ('x=',x:0:3,' ^ y=',y:0:3,'.');

end;

for i:=1 to 80 do

begin

delay(1);

write('_');

end;

writeln;

readkey;

end.

Edytowane przez _Mithrandir

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Zamiast:

 

--------------

if (wg=0) and (wx=0) and (wy=0) then

writeln ('Uklad nieoznaczony. ');

if (wg=0) then

if (wx<>0) or (wy<>0) then

writeln ('Uklad sprzeczny. ');

if wg<>0 then

begin

x:=wx/wg;

y:=wy/wg;

writeln ('ROZWIAZANIE:');

writeln;

writeln ('x=',x:0:3,' ^ y=',y:0:3,'.');

end;

--------------

 

Sproboj:

 

IF ((wg > -0.001) AND (wg < 0.001)) THEN
BEGIN
    IF ((wx > -0.001) AND (wx < 0.001)) AND    ((wy > -0.001) AND (wy < 0.001)) THEN
        writeln ('Uklad nieoznaczony. ')
    ELSE
        IF ((wx < -0.001) OR (wx > 0.001)) OR ((wy < -0.001) OR (wy > 0.001)) THEN
            writeln('Uklad sprzeczny. ');

END
ELSE
    begin
        x:=wx/wg;
        y:=wy/wg;
        writeln ('ROZWIAZANIE:');
        writeln;
        writeln ('x=',x:0:3,' ^ y=',y:0:3,'.');
    end;

Pokombinuj tez z tymi parametrami 0.001. Możesz je zmniejszyć np. do 0.00001 jeśli będzie potrzeba. Tak jak pisałem wcześniej: rozwiązywanie równań liniowych metodą wyznaczników nie bardzo nadaje się do obliczeń na komputerze, stąd możliwe niepoprawne wyniki. Normalnie stosuje sie inne algorytmy które mają mniejszy błąd obliczeń.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ok, rozumiem już o co chodzi. Wielkie dzięki, teraz działa :-)

A tak przy okazji: da się zrobić tak, żeby zamiast np. 1x+-1y=3 program wypisywał x-y=3? Tzn. bez przewidywania instrukcją "if" wszystkich możliwych przypadków dla danych liczb? (np. if a=1 then write..., if a=-1 then write ..., if (a=1) and (b=-1) then write..., itd.)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

hmmm... w Pascalu wątpie... w C/C++ można go zmusić do wypisywania znaku liczby... ale załatwienie tego IF-em nie jest złym pomysłem :D

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
IF ((wg > -0.001) AND (wg < 0.001)) THEN
BEGIN
    IF ((wx > -0.001) AND (wx < 0.001)) AND    ((wy > -0.001) AND (wy < 0.001)) THEN
        writeln ('Uklad nieoznaczony. ')
    ELSE
        IF ((wx < -0.001) OR (wx > 0.001)) OR ((wy < -0.001) OR (wy > 0.001)) THEN
            writeln('Uklad sprzeczny. ');

END
ELSE
    begin
        x:=wx/wg;
        y:=wy/wg;
        writeln ('ROZWIAZANIE:');
        writeln;
        writeln ('x=',x:0:3,' ^ y=',y:0:3,'.');
    end;

 

Przepisalem ten kod i po fragmencie writeln ('x=',x:0:3,' ^ y=',y:0:3,'.'); wyskoczyl mi blad "Error 26: Type Mismatch i nie wiem jak go mam naprawic, mogl by mi ktos pomoc?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

heh... typy sprawdź (czy nie są rozbieżne: np. obliczenia robisz w real, a wynik zapisujesz do integera).

 

I druga rzecz to fragment... nie cały program...

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

×
×
  • Dodaj nową pozycję...