Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.09.2011, 23:17   #1
ivan_b
 
Регистрация: 04.09.2011
Сообщений: 6
По умолчанию Алгоритм уравнивания

Пишу программу решающую химические уравнения, но столкнулся с такой ошибкой в алгоритме: при уравнивании сложных уравнений происходит зацикливание а отсюда переполнение типа => exitcode 215.

На простых уравнениях программа работала

алгоритм работы:
1 формулы веществ заносятся в массивы( с этим проблем нет);
2 по порядку следования элементов в уравнении проверяется одинаковое ли количество элемента в правой и левой части;
3 если количество одинаковое берется следующий элемент(далее шаг 2) разное происходит уравнивание:
Код:
procedure urovnat;//(el:integer);
var arrivl,arrivr:array[0..36,0..4] of integer;
arrivlc,arrivrc:integer;
ccc1,ccc2,ccc:integer;
lcount,rcount,koefl,koefr:integer;


begin
arrivlc:=0;
fillchar(arrivl,sizeof(arrivl),0);//îáíóëÿåì ìàñèâû
arrivrc:=0;
fillchar(arrivr,sizeof(arrivr),0);
lcount:=0;
rcount:=0;

   for ccc1:=0 to 6 do
        for ccc2:=1 to 6 do
          if left[ccc1,ccc2,1]=el then
                     begin
                     arrivl[arrivlc,0]:=el;
                     arrivl[arrivlc,1]:=left[ccc1,0,0];
                     arrivl[arrivlc,2]:=left[ccc1,ccc2,0];
                     arrivl[arrivlc,3]:=ccc2;
                     arrivl[arrivlc,4]:=ccc1;
                     arrivlc:=arrivlc+1;
                     end;

 for ccc1:=0 to 6 do
        for ccc2:=1 to 6 do
          if right[ccc1,ccc2,1]=el then
                     begin
                     arrivr[arrivrc,0]:=el;
                     arrivr[arrivrc,1]:=right[ccc1,0,0];
                     arrivr[arrivrc,2]:=right[ccc1,ccc2,0];
                     arrivr[arrivrc,3]:=ccc2;
                     arrivr[arrivrc,4]:=ccc1;
                     arrivrc:=arrivrc+1;
                     end;
ccc:=0;
repeat
lcount:=lcount+(arrivl[ccc,1]*arrivl[ccc,2]);
ccc:=ccc+1;
until (arrivl[ccc,1]=0) or (ccc=7);
ccc:=0;
repeat
rcount:=rcount+(arrivr[ccc,1]*arrivr[ccc,2]);
ccc:=ccc+1;
until (arrivr[ccc,1]=0) or (ccc=7);
koefl:=1;
koefr:=1;
if lcount>rcount then begin
        if (lcount mod rcount)=0 then koefr:=lcount div rcount
        else begin
        koefr:=lcount;
        koefl:=rcount;
        end;
end;
if lcount<rcount then begin
        if (rcount mod lcount)=0 then koefl:=rcount div lcount
        else begin
        koefr:=lcount;
        koefl:=rcount;
        end;//âû÷èñëÿåì êîåôèöèýíòû íà êîòîðûå ìíîæèìâñå ýëåìåíòû(âîçìîæíî íåäîðàáîòàí)
end;

   for arrivlc:=0 to 36 do
             begin
             if arrivl[arrivlc,0]=el then begin
             left[arrivl[arrivlc,4],0,0]:=left[arrivl[arrivlc,4],0,0] * koefl;
             left[arrivl[arrivlc,4],0,1]:=left[arrivl[arrivlc,4],0,1] * koefl;
             end;
             end;
   for arrivrc:=0 to 36 do
             begin
             if arrivr[arrivrc,0]=el then begin
             right[arrivr[arrivrc,4],0,0]:=right[arrivr[arrivrc,4],0,0] * koefr;
             right[arrivr[arrivrc,4],0,1]:=right[arrivr[arrivrc,4],0,1] * koefr;
             end;
             end;

end;
далее шаг 2 пока все не будет уровняно;

в связи с тем что происходило зацикливание было добавлено определение порядка в котором элементы уравниваются(в первую очередь те которых меньше всего и далее по возрастанию количества):
Код:
if if_run=false then  begin
upor:=0;
c1:=0;    c2:=0;
repeat

if leftcount[rivnnumberl,1]<>rightcount[rivnnumberr,1] then
        repeat

                rivnnumberr:=rivnnumberr+1;
        until leftcount[rivnnumberl,1]=rightcount[rivnnumberr,1];
        if leftcount[rivnnumberl,1]>0 then
                begin
                        nporyadok[c1,0]:=leftcount[rivnnumberl,0]+rightcount[rivnnumberr,0];
                        nporyadok[c1,1]:=rivnnumberl;
                        nporyadok[c1,2]:=leftcount[rivnnumberl,1];

                end;
rivnnumberl:=rivnnumberl+1;
c1:=c1+1;
rivnnumberr:=0;
until rivnnumberl>36;
for c1:=0 to 36 do begin
for c2:=0 to 36 do begin
        if nporyadok[c2,2]>0 then
        if upor=0 then begin upor:=nporyadok[c2,0]; uporc:=c2; st:=true; end
        else if (nporyadok[c2,0]<=upor) and (nporyadok[c2,0]>0) then begin
        upor:=nporyadok[c2,0];

          uporc:=c2;
           st:=true;
            end;
 end;

 if st then begin
 poryadok[c1,0]:=nporyadok[uporc,0];
  poryadok[c1,1]:=nporyadok[uporc,1];
 poryadok[c1,2]:=nporyadok[uporc,2];
 end;
  nporyadok[uporc,2]:=0;
 st:=false;
  upor:=0;
 end;
end;

 if_run:=true;
но и этот вариант не дал результата
уравнивание происходит по принципу коэффициент каждого вещества содержащего данный элемент умножается на число полученное в результате процедуры уравнивания(для правой и левой части числа разные).

Как исправить алгоритм чтобы не происходило зацикливание?
ivan_b вне форума Ответить с цитированием
Старый 05.09.2011, 00:06   #2
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,869
По умолчанию

если у Вас ищется общий множитель двух чисел, чтоб уравнять левую и правую части реакции, а эта процедура, думаю, там несомненно есть, то вот пример:
два числа: 6 и 8 - какой у них общий множитель: 6*8 = 48 - это самый простой ответ, но если подумать, то можно написать, что 24 (т.к. 8*3=24 и 6*4=24), т.е. если вы в программе сделаете дополнительно небольшую проверку своих коэффициентов, то они, скорее всего, не будут большими числами и программа не будет зависать. вы пробовали сначала решить сложную реакцию на бумаге и потом лишь задать её программе? такие же цифры получаются?
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.

Последний раз редактировалось NetSpace; 05.09.2011 в 00:09.
NetSpace вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Алгоритм TMDS (Алгоритм передачи данных интерфейса DVI) Pro4RE Помощь студентам 2 24.04.2011 21:55
Алгоритм Eugene_Brikov Помощь студентам 0 17.04.2011 10:59
Волновой алгоритм (алгоритм Ли) MrRockchip Общие вопросы C/C++ 4 10.05.2010 13:26
Алгоритм JoSkream Общие вопросы C/C++ 5 04.06.2009 23:22