[PASCAL] uklady rownan error: 'Division by zero'


(system) #1
uses crt;


procedure start;

begin

     clrscr;

     writeln('Program do obliczania ukladow rownan z dwoma niewiadomymi');

     writeln;

end;


procedure pierwsze_rownanie;

begin

     writeln('Pierwsze rownanie: ax+by=c ');

end;


function wczytanie_danych_1(var a,b,c:real):real;

begin

     write('Podaj czynnik a: ');

     readln(a);

     write('Podaj czynnik b: ');

     readln(b);

     write('Podaj czynnik c: ');

     readln(c);

end;


procedure drugie_rownanie;

begin

     writeln('Drugie rownanie: dx+ey=f');

end;


function wczytanie_danych_2(var d,e,f:real):real;

begin

     write('Podaj czynnik d: ');

     readln(d);

     write('Podaj czynnik e: ');

     readln(e);

     write('Podaj czynnik f: ');

     readln(f);

end;


function wyswietl_uklad(var a,b,c,d,e,f:real):real;

begin

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

end;



function wyznaczniki(var a,b,c,d,e,f,wg,wx,wy:real):real;

begin


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

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

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


end;


function obliczenia(x,y,w,wx,wy:real):real;

begin

x:=wx/w;

y:=wy/w;

writeln('y= ',x);

writeln('y= ',y);

end;


function rozwiazania(x,y,wg,wx,wy,a,b,c,d,e,f:real):real;

begin

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;


end;


var

a,b,c,d,e,f:real;

wg,wx,wy,x,y,w:real;


begin

     start;

     writeln;

     pierwsze_rownanie;

     wczytanie_danych_1(a,b,c);

     writeln;

     drugie_rownanie;

     wczytanie_danych_2(d,e,f);

     writeln;

     wyswietl_uklad(a,b,c,d,e,f);

     writeln;

     obliczenia(x,y,w,wx,wy);

     rozwiazania(x,y,wx,wy,w,a,b,c,d,e,f);

     readln;

end.

Problem tkwi w tym, że gdy podaje jakiekolwiek liczby to wyskakuje błąd podany w temacie, nigdy nie spotkałem się z takim błędem nie wiem ocb ;/

w necie znalazłem takie coś

hmm ciekawe.

Proszę o pomoc


(Gardner) #2

A ten błąd to przypadkiem nie "Divide by zero"? Po prostu w którymś miejscu, gdzie dzielisz, dzielnik jest równy zero, a nawet komputer nie umie podzielić liczby przez 0.


(lukjac) #3

Masz starą wersję Pascala,

pobierz patcha np. stąd

http://www.programowanie.virtual.avx.pl/?page=5

lub wersję komplilatora, w którym naprawiono ten błąd


(system) #4

ściągnąłem i dalej ten błąd ;/

a jakby to przerobić, ofc muszę być procedury/funkcje bo to mam wymagane

nie, podawałem same 2,2,2,2,2,2,2 dla testu

później oczywiście inne i dalej to samo ;/


(Simplex111) #5

Tak na szybko zauważyłem, że w funkcji obliczenia używasz zmiennej " w", której nigdzie nie zainicjowałeś i stąd dzielenie przez zero

function obliczenia(x,y,w,wx,wy:real):real;

begin

x:=wx/w; (* Tu jest błąd *)

y:=wy/w;

writeln('y= ',x);

writeln('y= ',y);

end;

Być może ta zmienna nie jest potrzebna. Na próbę wstawiłem na początku programu instrukcję w:= 1; i program się wykonuje i podaje wynik (choć zapewne błędny).


(system) #6

to 'w' to powinno być 'wg'

ale po przemienieniu dalej nie działa

uses crt;


procedure start;

begin

     clrscr;

     writeln('Program do obliczania ukladow rownan z dwoma niewiadomymi');

     writeln;

end;


procedure pierwsze_rownanie;

begin

     writeln('Pierwsze rownanie: ax+by=c ');

end;


function wczytanie_danych_1(var a,b,c:real):real;

begin

     write('Podaj czynnik a: ');

     readln(a);

     write('Podaj czynnik b: ');

     readln(b);

     write('Podaj czynnik c: ');

     readln(c);

end;


procedure drugie_rownanie;

begin

     writeln('Drugie rownanie: dx+ey=f');

end;


function wczytanie_danych_2(var d,e,f:real):real;

begin

     write('Podaj czynnik d: ');

     readln(d);

     write('Podaj czynnik e: ');

     readln(e);

     write('Podaj czynnik f: ');

     readln(f);

end;


function wyswietl_uklad(var a,b,c,d,e,f:real):real;

begin

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

end;



function wyznaczniki(var a,b,c,d,e,f,wg,wx,wy:real):real;

begin


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

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

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


end;


function obliczenia(var x,y,wg,wx,wy:real):real;

begin

x:=wx/wg;

y:=wy/wg;

writeln('y= ',x);

writeln('y= ',y);

end;


function rozwiazania(x,y,wg,wx,wy,a,b,c,d,e,f:real):real;

begin

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;


end;


var

a,b,c,d,e,f:real;

wg,wx,wy,x,y,w:real;


begin

     start;

     writeln;

     pierwsze_rownanie;

     wczytanie_danych_1(a,b,c);

     writeln;

     drugie_rownanie;

     wczytanie_danych_2(d,e,f);

     writeln;

     wyswietl_uklad(a,b,c,d,e,f);

     writeln;

     obliczenia(x,y,w,wx,wy);

     rozwiazania(x,y,wx,wy,w,a,b,c,d,e,f);

     readln;

end.

(Simplex111) #7

Nie działa, bo w dalszym ciągu nie obliczasz wyznaczników - nie wywołujesz funkcji wyznaczniki

....

     wyswietl_uklad(a,b,c,d,e,f);

     writeln;

     (* tu wstaw wywołanie funkcji wyznaczniki *)

     obliczenia(x,y,w,wx,wy); (* dlaczego dalej "w", a nie "wg"

     rozwiazania(x,y,wx,wy,w,a,b,c,d,e,f);

     readln;

end.

(system) #8

no ok wiem jestem oporny ale muszę widzieć żeby zrozumieć

uses crt;


procedure start;

begin

     clrscr;

     writeln('Program do obliczania ukladow rownan z dwiema niewiadomymi');

     writeln;

end;


procedure pierwsze_rownanie;

begin

     writeln('Pierwsze rownanie: ax+by=c ');

end;


function wczytanie_danych_1(var a,b,c:real):real;

begin

     write('Podaj czynnik a: ');

     readln(a);

     write('Podaj czynnik b: ');

     readln(b);

     write('Podaj czynnik c: ');

     readln(c);

end;


procedure drugie_rownanie;

begin

     writeln('Drugie rownanie: dx+ey=f');

end;


function wczytanie_danych_2(var d,e,f:real):real;

begin

     write('Podaj czynnik d: ');

     readln(d);

     write('Podaj czynnik e: ');

     readln(e);

     write('Podaj czynnik f: ');

     readln(f);

end;


function wyswietl_uklad(var a,b,c,d,e,f:real):real;

begin

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

end;



function wyznaczniki(var a,b,c,d,e,f,wg,wx,wy:real):real;

begin


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

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

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


end;


function obliczenia(var x,y,wg,wx,wy:real):real;

begin

x:=wx/wg;

y:=wy/wg;

end;


function rozwiazania(x,y,wg,wx,wy,a,b,c,d,e,f:real):real;

begin

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;


end;


var

a,b,c,d,e,f:real;

wg,wx,wy,x,y,w:real;


begin

     start;

     writeln;

     pierwsze_rownanie;

     wczytanie_danych_1(a,b,c);

     writeln;

     drugie_rownanie;

     wczytanie_danych_2(d,e,f);

     writeln;

     wyswietl_uklad(a,b,c,d,e,f);

     writeln;

     wyznaczniki(a,b,c,d,e,f,wg,wy,wx);

     rozwiazania(x,y,wx,wy,w,a,b,c,d,e,f);

     obliczenia(a,b,c,d,e);

     readln;

end.

teraz x=0 dla każdego przypadku z tego co odnotowałem i nie wiem czy y dobrze liczy ;/

eh i nie wypisuje czy układ oznaczony itp...

plox dla wytłumaczcie jak dla lajka


(Simplex111) #9

Ta wersja powinna już obliczać poprawnie:

program UkladRownan;


    uses crt;


    procedure start;

    begin

         clrscr;

         writeln('Program do obliczania ukladow rownan z dwoma niewiadomymi');

         writeln;

    end;


    procedure pierwsze_rownanie;

    begin

         writeln('Pierwsze rownanie: ax+by=c ');

    end;


    function wczytanie_danych_1(var a,b,c:real):real;

    begin

         write('Podaj czynnik a: ');

         readln(a);

         write('Podaj czynnik b: ');

         readln(b);

         write('Podaj czynnik c: ');

         readln(c);

    end;


    procedure drugie_rownanie;

    begin

         writeln('Drugie rownanie: dx+ey=f');

    end;


    function wczytanie_danych_2(var d,e,f:real):real;

    begin

         write('Podaj czynnik d: ');

         readln(d);

         write('Podaj czynnik e: ');

         readln(e);

         write('Podaj czynnik f: ');

         readln(f);

    end;


    function wyswietl_uklad(var a,b,c,d,e,f:real):real;

    begin

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

    end;



    function wyznaczniki(var a,b,c,d,e,f,wg,wx,wy:real):real;

    begin


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

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

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


    end;


    function obliczenia(var x,y,wg,wx,wy:real):real;

    begin

    x:=wx/wg;

    y:=wy/wg;

    writeln('x= ',x);

    writeln('y= ',y);

    end;


    function rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f:real):real;

    begin

    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;


    end;


    var

    a,b,c,d,e,f:real;

    wg,wx,wy,x,y,w:real;


    begin

         start;

         writeln;

         pierwsze_rownanie;

         wczytanie_danych_1(a,b,c);

         writeln;

         drugie_rownanie;

         wczytanie_danych_2(d,e,f);

         writeln;

         wyswietl_uklad(a,b,c,d,e,f);

         writeln;

         wyznaczniki(a,b,c,d,e,f,wg,wx,wy);

         obliczenia(x,y,wg,wx,wy);

         rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f);

         readln;

    end.

Delikatnie mówiąc w Twoim kodzie jest trochę bałaganu, co powoduje, że bardzo łatwo jest o pomyłkę, literówkę i to powoduje późniejsze błędy przy kompilacji lub wykonywaniu programu.

Wieczorem będę miał więcej czasu, więc postaram się napisać kilka uwag (chyba, że ktoś z forumowiczów mnie uprzedzi :wink: )

Zajrzyj więc tu jeszcze.


(system) #10

Na pewno zajrzę co nie znaczy ze sam tez nie będę próbował.

EDIT:

done Szefie


(Airborn) #11

hondus , na forum obowiązują zasady pisowni języka polskiego, włącznie z polskimi znakami diakrytycznymi. Proszę poprawić wszystkie swoje posty.


(Simplex111) #12

Tak jak obiecałem, oto moje uwagi do twojego programu.

Jeśli chodzi o komunikat błędu "Division by zero" - w pierwszej wersji programu próbowałeś się odwołać do zmiennej bez uprzedniego nadania jej wartości początkowej. W przypadku Pascala kompilator sam nadaje wartości początkowe deklarowanym zmiennym zależnie od typu:

zmienne całkowite i rzeczywiste - zero

zmienne typu string - łańcuch pusty ('')

zmienne logiczne - false

ale nie warto na tym polegać i lepiej zrobić to samemu (może się zdarzyć, że inny kompilator tego nie będzie robił i wówczas wartość zmiennej będzie nieokreślona) Na Twoje nieszczęście akurat zmiennej, której nie zainicjowałeś została przypisana wartość 0.

Zmienne globalne najlepiej deklarować na początku programu, zaraz po deklaracjach uses i type, przed odwoływaniem się do tych zmiennych w funkcjach, czy procedurach (mimo iż kompilator pozwala robić to później, przed rozpoczęciem bloku głównego programu)

W Pascalu w nazwach zmiennych, czy procedur przyjęło się stosować tzw Styl wielbłądzi np: MojaPierwszaProcedura (podkreślenie to raczej w innych językach). Tu masz link do artykułu na temat Zasad pisania kodu

Funkcja czy procedura. W Pascalu jest podział na funkcje i procedury (w innych językach mogą być tylko funkcje). Zasada jest taka, że procedura tylko wykonuje pewne instrukcje, a funkcja oblicza jedną wartość oraz ją udostępnia. Wywołanie funkcji następuje za pomocą podania nazwy funkcji jako argumentu dowolnego wyrażenia. Lepiej pokazać to na przykładzie:

procedure Suma1(a, b: Integer, var Wynik: Integer);

begin

  Wynik:= a + b;

end;


function Suma2(a, b: Integer): Integer;

begin

  Suma2:= a + b;

end;

A teraz użycie w bloku głównym programu:

var a, b, Suma: Integer;

begin

  a:= 1;

  b:= 2;

  (* procedura *)

  Suma1(a, b, Suma); (* Procedura zapisuje wynik do zmiennej Suma *)

  Writeln('Suma = ', Suma);

  (* funkcja *)

  Suma:= Suma2(a, b); (* Zmiennej Suma jest przypisywana wartość funkcji Suma2 *)

  Writeln('Suma = ', Suma);

  (* Zamiast dwóch linijek powyżej można krócej *)

  Writeln('Suma = ', Suma2(a, b));

end.

Niektóre kompilatory Pascala pozwalają na wywoływanie funkcji jak procedur, ale w starszych wersjach (np turbo Pascal 5.5) kompilacja by się nie udała. W przypadku Twojego programu zastosowałbym procedury, może za wyjątkiem funkcji Wyznaczniki i Obliczenia (po odpowiedniej modyfikacji). Definiowanie bloku programu jako procedury. Generalnie warto to robić nawet, jeśli dana procedura, bądź funkcja miałaby być wywoływana tylko raz, pod warunkiem, że uprości to kod i zwiększy jego czytelność. Natomiast, jeżeli mamy dwie procedury, które wykonują podobne instrukcje, ale na innych zmiennych, to można je zastąpić jedną z odpowiednimi parametrami. Dłuższy kod wcale nie musi być lepszy. Poniżej procedura wczytująca dane

procedure WczytajDaneRownania(Tekst: string; a1, b1, c1: Char; var a, b, c: Real);

begin

  Writeln(Tekst);

  Write('Podaj czynnik ', a1, ': ');

  Readln(a);

  Write('Podaj czynnik ', b1, ': ');

  Readln(b);

  Write('Podaj czynnik ', c1, ': ');

  Readln(c);

end;

Zauważ, że w definicji procedury fragment var a, b, c: Real nie oznacza wcale, że musimy operować na zmiennych globalnych a, b, c (to tylko zbieżność nazw). Poczytaj o parametrach formalnych i parametrach aktualnych. Wywołując procedurę możemy wstawić dowolne zmienne np. d, e, f. Widać to w drugim wywołaniu:

WczytajDaneRownania('Pierwsze równanie: ax + by = c', 'a', 'b', 'c', a, b, c);

WczytajDaneRownania('Drugie równanie: dx + ey = f', 'd', 'e', 'f', d, e, f);

Jeszcze jedna uwaga: w definicji procedury w miejscu, gdzie podajemy parametry niektóre są poprzedzone słowem var. Są to parametry przekazywane przez zmienną, a stosujemy je wówczas, gdy chcemy aby ich wartość była znana również poza procedurą (poczytaj również o parametrach przekazywanych przez wartość lub przez zmienną). Co do porównywania wyznaczników układu równań do zera. Myślę, że można to zrobić wprost, ponieważ przy ich obliczaniu występuje tylko mnożenie i dodawanie liczb wymiernych, a wiec zawsze będą liczbami wymiernymi i komputer będzie mógł przyrównać je do zera. Uff, trochę się tego nazbierało! Mam nadzieję, że doczytałeś do końca. :slight_smile: Oto moja wersja programu po modyfikacjach, choć zapewne nie jest jeszcze doskonała. Można w nim wiele rzeczy zmienić, poprawić, więc ... próbuj :wink:

program UkladRownan;

uses crt;

var

  a,b,c,d,e,f: real;

  wg,wx,wy,x,y: real;


procedure start;

begin

  clrscr;

  writeln('Program do obliczania ukladow rownan z dwoma niewiadomymi');

  writeln;

end;


procedure WczytajDaneRownania(Tekst: string; a1, b1, c1: Char; var a, b, c: Real);

begin

  Writeln(Tekst);

  Write('Podaj czynnik ', a1, ': ');

  Readln(a);

  Write('Podaj czynnik ', b1, ': ');

  Readln(b);

  Write('Podaj czynnik ', c1, ': ');

  Readln(c);

  Writeln;

end;


procedure WyswietlUklad(a,b,c,d,e,f:real);

begin

  writeln('Uklad rownan:');

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

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

end;


procedure Wyznaczniki(a,b,c,d,e,f: Real; var wg,wx,wy: real);

begin

  wg:= a*e - d*b;

  wx:= c*e - f*b;

  wy:= a*f - d*c;

end;


procedure Rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f:real);

begin

  if wg = 0 then

  begin

    if (wx = 0) and (wy = 0) then writeln ('Uklad nieoznaczony.')

    else writeln('Uklad sprzeczny.');

  end

  else

  begin

    x:= wx/wg;

    y:= wy/wg;

    writeln('MA JEDNO ROZWIAZANIE:');

    writeln;

    writeln('x = ',x:0:3);

    writeln('y = ',y:0:3);

  end;

end;


begin

  Start;

  writeln;

  WczytajDaneRownania('Pierwsze rownanie: ax + by = c', 'a', 'b', 'c', a, b, c);

  WczytajDanerownania('Drugie rownanie: dx + ey = f', 'd', 'e', 'f', d, e, f);

  WyswietlUklad(a,b,c,d,e,f);

  Writeln;

  Wyznaczniki(a,b,c,d,e,f,wg,wx,wy);

  Rozwiazania(x,y,wx,wy,wg,a,b,c,d,e,f);

  Readln;

end.

(system) #13

Ślicznie dziękuje za pomoc. jestem wzrokowcem i lepiej do mnie trafia obraz (czytaj:kod) niż wyklepane definicje. usiądę na pewno nad wszystkimi zagadnieniami, nieco pomogłeś mi odróżnić funkcje od procedury (bo to mój największy problem, z niedbałym pisaniem kodu powoli się uporam). jeszcze raz śliczne dzięki wszystkim za pomoc