Wielomian 3 stopnia – program wiesza się

0

Witam,
znajomy dostał od prowadzącego na uczelni zadanie do wykonania (załącznik), a ja staram się mu je rozwiązać. Polega ono na znalezieniu koncentracji składnika c dla podanego równania.
Metodą jaką wybrałem jest metoda Newtona. Napisałem kod w Pascalu niestety nie do końca działa on tak jak bym chciał. Przy wprowadzeniu wartości początkowej c dla której algorytm ma zacząć obliczać miejsce zerowe i dokładności program wiesza się jeśli dokładność jest większa niż 0.001. Nie wiem czy to wina mojego słabego laptopa czy to jakiś błąd w kodzie. Bardzo proszę o pomoc.

program Untitled;

uses crt;

type
	tablica = array[1..100000] of real;

var
	c: tablica;
	Q,cin,k,K1,V,f,g,z,eps: real;
	n: integer;

begin
	clrscr;

WriteLn('Program oblicza koncentracje koncowa skladnika c w reaktorze z idealnym wymieszaniem metoda Newtona.');
Write('Podaj Q: ');
ReadLn(Q);
Write('Podaj cin: ');
ReadLn(cin);
Write('Podaj k: ');
ReadLn(k);
Write('Podaj K1: ');
ReadLn(K1);
Write('Podaj V: ');
ReadLn(V);
Write('Podaj x: ');
ReadLn(c[1]);
Write('Podaj dokladnosc obliczen: ');
ReadLn(eps);

n:=1;

repeat
	f:=Q*c[n]+2*Q*K1*c[n]*c[n]+Q*K1*K1*c[n]*c[n]*c[n]-Q*cin-2*Q*cin*K1*c[n]-Q*cin*K1*K1*c[n]*c[n]+V*k*c[n];
      	g:=Q+4*Q*K1*c[n]+3*Q*K1*K1*c[n]*c[n]-2*Q*cin*K1-2*Q*cin*K1*K1*c[n]+V*k;
      	c[n+1]:=c[n]+(f/g);
      	z:=c[n+1]-c[n];
until
      	z<eps;

WriteLn('Szukane stezenie c wynosi: ',c[n+1]);

ReadLn();

end.

0

Wartość zmiennej n nie zmienia się w tej pętli, a powinna.

Poza tym, ten kod jest dość nieczytleny i pasowałoby go sformatować.

0

Dodałem na końcu pętli inkrementację zmiennej n jednak wiele to nie pomogło. Teraz po uruchomieniu programu i wczytaniu zmiennych program wyrzuca błąd po którym konsola automatycznie się zamyka przez co nie jestem nawet w stanie zorientować się w czym rzecz. Co do formatowania kodu, to nie jestem programistą. Starałem się zastosować do instrukcji publikacji kodu, jeśli czegoś nie zrobiłem to powiedz proszę w czym rzecz, a następnym razem na pewno zrobię to lepiej.

repeat
      f:=Q*c[n]+2*Q*K1*c[n]*c[n]+Q*K1*K1*c[n]*c[n]*c[n]-Q*cin-2*Q*cin*K1*c[n]-Q*cin*K1*K1*c[n]*c[n]+V*k*c[n];
      g:=Q+4*Q*K1*c[n]+3*Q*K1*K1*c[n]*c[n]-2*Q*cin*K1-2*Q*cin*K1*K1*c[n]+V*k;
      c[n+1]:=c[n]+(f/g);
      z:=c[n+1]-c[n];
      n:=n+1;
until
      z<eps;
1
Atsutane napisał(a):

Teraz po uruchomieniu programu i wczytaniu zmiennych program wyrzuca błąd po którym konsola automatycznie się zamyka przez co nie jestem nawet w stanie zorientować się w czym rzecz.

Jak to nie – uruchom program z wiersza poleceń i zobacz co wyrzuciło. Albo skorzystaj z debuggera.

Co do formatowania kodu, to nie jestem programistą.

Nie trzeba być programistą, aby widzieć, że jeden ciąg znaków długaśnego wyrażenia bardzo źle się czyta. Przydałoby się chociaż rozsunąć fragmenty pomiędzy odejmowaniem – już łatwiej będzie.


Sprawdź ten kod pod debuggerem – postaw breakpoint na pierwszej linijce w pętli, wrzuć sobie zmienne do okna watches i klawiszem F8 wykonuj po jednej linijce, obserwując co ostatecznie wpisywane jest do zmiennych.

Poza tym, warunek końcowy pętli nie zabezpiecza przed wyjściem poza zakres tablicy, przez co n może być większe niż 100.000. Dlatego też na sam początek zmień ten warunek na taki:

until (n = 100000) or (z < eps);

Końcowe wyświetlanie danych też trzeba zabezpieczyć, bo również możesz wyjść poza zakres tablicy tym c[n+1].

0

c[n+1]:=c[n]+(f/g);
A co to za wersja metody Newtona??
chyba miało być
c[n+1]:=c[n]-(f/g);

To samo z warunkiem zakończenia. Różnica z:=c[n+1]-c[n]; może wyjść -500 i wyjdzie z pętli a warunek nie będzie spełniony dla metody. Wartość różnicy ma być bezwzględna!

1

W jakim celu zapisujesz do tablicy o stałym rozmiarze kolejne wyniki? Raz że ryzykujesz wyjście poza jej wymiar, dwa, te dane nie są do niczego potrzebne. Wystarczy że będziesz pamiętał w zmiennej wynik z poprzedniej iteracji.

0

W metodzie Newtona rzeczywiście miałem zły znak, wyłapałem to jak przeliczałem sobie algorytm w głowie. Co do wartości absolutnej zupełnie o tym zapomniałem wobec czego stokrotne dzięki za wskazówkę.
Co się zaś tyczy tablicy o stałym rozmiarze to nie wiem czemu ją stosuję. Zawsze jej używałem, ponieważ tak było mi najprościej. Obliczenia które wykonywał program zawsze sprawdzałem sobie w excel'u czy program wyjdzie poza skalę i odpowiednio dobierałem rozmiar tablicy. Nie bardzo wiedziałem jednak o co chodziło Panu powyżej więc zrobiłem to na czuja i program działa. Jednakże, jeśli nie o to chodziło to chciałbym prosić o informację aby w przyszłości nie popełnić podobnego błędu. Na sam koniec mam pytanie dotyczące tablicy o stałym rozmiarze. Znalazłem już informację, że tablice o zmiennym rozmiarze istnieją, jednak czy używanie ich jest na poziomie laika jakim jestem, jeśli chodzi o programowanie?

program Untitled;

uses crt;

var

Q,cin,k,K1,V,f,g,z,eps,c,m: real;
l: integer;
p: char;

begin

repeat
	clrscr;
	WriteLn('Program oblicza koncentracje koncowa skladnika c metoda Newtona.');
	Write('Podaj Q: ');
	ReadLn(Q);
	Write('Podaj cin: ');
	ReadLn(cin);
	Write('Podaj k: ');
	ReadLn(k);
	Write('Podaj K1: ');
	ReadLn(K1);
	Write('Podaj V: ');
	ReadLn(V);
	Write('Podaj x: ');
	ReadLn(m);
	Write('Podaj dokladnosc obliczen: ');
	ReadLn(eps);
	
	repeat
	      f:=Q*m + 2*Q*K1*m*m + Q*K1*K1*m*m*m - Q*cin - 2*Q*cin*K1*m - Q*cin*K1*K1*m*m + V*k*m;
	      g:=Q + 4*Q*K1*m + 3*Q*K1*K1*m*m - 2*Q*cin*K1 - 2*Q*cin*K1*K1*m + V*k;
	      c:=m - (f/g);
	      z:=abs(c - m);
	      m:=c;
	until
	      z<eps;
	
	WriteLn('Ile miejsc po przecinku program ma wyswietlic w wyniku?');
	ReadLn(l);
	clrscr;
	WriteLn('Szukane stezenie c wynosi: ',c:l+2:l);
	WriteLn();
	WriteLn('Czy chcesz zmienic warunki zadania? T/N');
	ReadLn(p);
until
	p='N';

ReadLn();


end.

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