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

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

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 21.01.2015, 02:15   #1
Armageddets
Форумчанин
 
Регистрация: 30.06.2012
Сообщений: 145
Сообщение Нет попадания в цикл

Всем доброго времени суток. Пишу программу по математическим расчетам. В процессе ее создания столкнулся с проблемой. В коде одной из процедур есть цикл, внутрь которого я попадаю только первый раз, а затем никогда не вхожу в него, хотя подобных условий или любых других для входа в него нет. Отслеживал значения в if then - там проверяются и выполняются условия, но внутрь все равно попадает лишь первый раз. Подскажите с чем это может быть связано. Работаю в Delphi 7 lite.

Код:

Код:

procedure Shag4;
var i,j,ii,jj,xc,yc,xx,yy,n:Integer;
min:Double;
mins,del:Integer; //ostavlaemaya stroka/stolbets (slev/sverhu)
result:array[0..1,0..1] of Double;
m:boolean;
begin

  //obnulenie klasterov
  for i:=0 to Stroki-3 do
  klasters[i]:=0;
  klMax:=1;
  //n:=0;
  //======================================================
  //obyedinenie v klasteri
  while (form2.StringGrid1.RowCount-1 >=1) do
  begin

    //ishem minimum
    min:=9999999999;
    for j:=0 to (form2.StringGrid1.RowCount-1) do
    for i:=0 to (form2.StringGrid1.RowCount-1) do
    begin
      if ( ( min > StrToFloat(form2.StringGrid1.Cells[i,j]) ) and (i<>j) ) then
      begin
      min:=StrToFloat(form2.StringGrid1.Cells[i,j]);
      xc:=i;
      yc:=j;
        //kakaya stroka/stolbets ostanetsya
        if xc<yc then mins:=xc else mins:=yc;
        //kakaya stroka/stolbets udalitsya
        if xc<yc then del:=yc else del:=xc;
      end;
    end;

    //sravnivaem znacheniya na minimum po dvum strokam i stolbtsam
    for i:=0 to (form2.StringGrid1.RowCount-1) do
    begin
      //po strokam dlya stolbtsov sravnenie
      if StrToFloat(form2.StringGrid1.Cells[mins,i])>StrToFloat(form2.StringGrid1.Cells[del,i]) then
      form2.StringGrid1.Cells[mins,i]:=form2.StringGrid1.Cells[del,i];

      //po stolbtsam dlya strok sravnenie
      if StrToFloat(form2.StringGrid1.Cells[i,mins])>StrToFloat(form2.StringGrid1.Cells[i,del]) then
      form2.StringGrid1.Cells[i,mins]:=form2.StringGrid1.Cells[i,del];
    end;

      
      //ishem pravilnie koordinati v nachalnoy tablitse (eshe ne sokrashennoy ni razu)
      for j:=0 to Stroki-3 do
      for i:=0 to Stroki-3 do
      begin
        if (klas[i,j]=min) then
        begin
        //===========================
        xc:=i;
        yc:=j;
        //===========================
        end;

      end;

  end;

end;
Место, куда мне нужно попадать постоянно в цикле я выделил знаками равно. В проверке if (klas[i,j]=min) then я уже отслеживал проверку на равенство (она выполняется) но внутрь бегина и энда программа все равно не идет, а продолжает дальше искать варианты...

Заранее спасибо всем, кто откликнется. Реально впервые с таким столкнулся (
Armageddets вне форума Ответить с цитированием
Старый 21.01.2015, 07:41   #2
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Тут есть 2 варианта.
Либо Вы некорректно определяете, что проверка выполняется.
Либо Вы впервые в жизни столкнулись с Особенностями вещественных чисел (раздел Примеры «неправильного» поведения вещественных типов) и настало время принять за правило использовать Math.CompareValue для сравнения вещественных чисел.
Но это актуально для случая когда Вы полагаетесь в проверке на выполнение в виде визуального сравнения чисел (стандартным дельфёвым эвалюатором), а не проверкой результата сравнения (тоже им же, но когда он пишет всё_выражение = True/False).

В общем, без проекта (плюс идентичных с Вашими тестовыми данными) и детального дебага - сказать что-то однозначно сложно.
phomm вне форума Ответить с цитированием
Старый 21.01.2015, 07:49   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

По-моему все правильно. Оптимизатор посчитал ненужным сам цикл.
Проверь - обрами эту часть в директивы {$o-}...{$o+} и пройдись отладкой.
Но мне к примеру тоже было бы неясно зачем нужны присвоения xc:=i; и yc:=j; в данном случае в последнем цикле.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.01.2015, 08:50   #4
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Хм, переменные локальные, не проверил сперва, по идее оптимизатор тогда должен выкинуть всё, а по утверждению автора, один раз всё таки заходит.
Автор, а зачем действительно присвоение в локальные переменные, если больше они нигде не используются ? Возможно, Вы от нас "в целях сокращения" скрыли часть кода ?
phomm вне форума Ответить с цитированием
Старый 21.01.2015, 10:34   #5
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
а по утверждению автора, один раз всё таки заходит.
Это не совсем так. Я уверен что ТС не все нам рассказал )
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.01.2015, 11:07   #6
Armageddets
Форумчанин
 
Регистрация: 30.06.2012
Сообщений: 145
По умолчанию

Да часть кода скрыл, в конце процедуры. Сейчас покажу весь проект. И первый раз я таки попадаю в цикле туда, а потом не хочет.

Вот мои глобальные переменные:

Код:

var
  Form1: TForm1;
  MsExcel: Variant;
  path:string;
  mas:array of array of Double;
  klasters:array of Integer;
  Stroki:Integer;
  klas,klas2:array of array of Double;
  SrZnach,Fi:Double;
  Element:array of Double;
  klMax:Integer; //maximalniy nomer klastera
  Buf:TBitmap;
  Kn:array[1..5,1..2] of TBitmap;
  Fon:TJPEGImage;
  Vis,Activ:integer; //vidimaya knopka i aktivnaya
  function Xls_To_StringGrid(AGrid: TStringGrid; AXLSFile: string): Boolean;
  procedure StringGrid_TO_XL;
  procedure Shag1(Stringgrid:TStringGrid);
  procedure Shag2;
  procedure Shag3;
  procedure Shag4;
  procedure GridDeleteRow(RowNumber: Integer; Grid: TstringGrid);
  procedure GridDeleteCol(ColNumber: Integer; Grid: TstringGrid);
  procedure dd(SG:TstringGrid;ii:integer;jj:integer);

...

А вот вся процедура:

procedure Shag4;
var i,j,ii,jj,xc,yc,xx,yy,n:Integer;
min:Double;
mins,del:Integer; //ostavlaemaya stroka/stolbets (slev/sverhu)
result:array[0..1,0..1] of Double;
m:boolean;
begin

  //obnulenie klasterov
  for i:=0 to Stroki-3 do
  klasters[i]:=0;
  klMax:=1;
  //n:=0;
  //======================================================
  //obyedinenie v klasteri
  while (form2.StringGrid1.RowCount-1 >=1) do
  begin

    //ishem minimum
    min:=9999999999;
    for j:=0 to (form2.StringGrid1.RowCount-1) do
    for i:=0 to (form2.StringGrid1.RowCount-1) do
    begin
      if ( ( min > StrToFloat(form2.StringGrid1.Cells[i,j]) ) and (i<>j) ) then
      begin
      min:=StrToFloat(form2.StringGrid1.Cells[i,j]);
      xc:=i;
      yc:=j;
        //kakaya stroka/stolbets ostanetsya
        if xc<yc then mins:=xc else mins:=yc;
        //kakaya stroka/stolbets udalitsya
        if xc<yc then del:=yc else del:=xc;
      end;
    end;

    //sravnivaem znacheniya na minimum po dvum strokam i stolbtsam
    for i:=0 to (form2.StringGrid1.RowCount-1) do
    begin
      //po strokam dlya stolbtsov sravnenie
      if StrToFloat(form2.StringGrid1.Cells[mins,i])>StrToFloat(form2.StringGrid1.Cells[del,i]) then
      form2.StringGrid1.Cells[mins,i]:=form2.StringGrid1.Cells[del,i];

      //po stolbtsam dlya strok sravnenie
      if StrToFloat(form2.StringGrid1.Cells[i,mins])>StrToFloat(form2.StringGrid1.Cells[i,del]) then
      form2.StringGrid1.Cells[i,mins]:=form2.StringGrid1.Cells[i,del];
    end;


      //ishem pravilnie koordinati v nachalnoy tablitse (eshe ne sokrashennoy ni razu)
      //m:=false;
      for j:=0 to Stroki-3 do
      for i:=0 to Stroki-3 do
      begin

        if ( Round(klas[i,j]) = Round(min) ) then
        begin
        xc:=i;
        yc:=j;
        end;

      end;

      //zapomnit razbienie na klasteri
      if (klasters[xc]=0) and (klasters[yc]=0) then
      begin
        klasters[xc]:=klMax;
        klasters[yc]:=klMax;
        Inc(klMax);
      end;
      if (klasters[xc]>0) and (klasters[yc]=0) then klasters[yc]:=klasters[xc];
      if (klasters[yc]>0) and (klasters[xc]=0) then klasters[xc]:=klasters[yc];
    //dd(form1.StringGrid1,x,y);
    //form2.StringGrid1.Cells[x,2]:=form2.StringGrid1.Cells[x,2]+'-'+form2.StringGrid1.Cells[y,2];
    GridDeleteRow(del,form2.StringGrid1); //udalit stroku
    GridDeleteCol(del,form2.StringGrid1); //udalit stolbets
    form2.StringGrid1.Refresh;          //obnovit vid tablitsi
    //end;


    //result dlya tablitsi
    if form2.StringGrid1.RowCount-1 = 1 then
    begin
      for i:=0 to 1 do
      for j:=0 to 1 do
      result[i,j]:=StrToFloat(Form2.StringGrid1.Cells[i,j]);
    end;

    //Inc(n);

  end;


  //ostavsheesya znachenie opredelyaem v klaster
  for i:=0 to Stroki-3 do
  if klasters[i]=0 then klasters[i]:=klMax;


  Form2.StringGrid1.ColCount:=Form2.StringGrid1.ColCount+1;
  Form2.StringGrid1.RowCount:=Form2.StringGrid1.RowCount+1;
    //pokaz resulta
    for i:=0 to 1 do
    for j:=0 to 1 do
    Form2.StringGrid1.Cells[i,j]:=FloatToStr(result[i,j]);


  Form2.StringGrid1.Width:=Form2.StringGrid1.ColCount*40+10;
  Form2.StringGrid1.Height:=Form2.StringGrid1.RowCount*20+15;
  Form2.ClientWidth:=Form2.StringGrid1.Width+20;
  Form2.ClientHeight:=Form2.StringGrid1.Height+20;
  
end;
А вот полный исходник. Так как его размер превышает разрешенные для заливки сюда, то я его залил на ргхост:
http://rghost.ru/60470344

Последний раз редактировалось Armageddets; 21.01.2015 в 14:25.
Armageddets вне форума Ответить с цитированием
Старый 21.01.2015, 12:33   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Ну отключи оптимизатор - посмотришь что будет.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.01.2015, 13:12   #8
Armageddets
Форумчанин
 
Регистрация: 30.06.2012
Сообщений: 145
По умолчанию

Отключил оптимизатор и все равно заходит только первый раз (два раза за один проход цикла while). Загружаю для проверки документ с именем "пример1". Для проверки, ставлю точки прерывания и использую add watch.

Последний раз редактировалось Armageddets; 21.01.2015 в 13:17.
Armageddets вне форума Ответить с цитированием
Старый 21.01.2015, 19:52   #9
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Я погонял прогу, правда кажется на примере пример.хлс а не пример1.хлс , но не факт, что это имеет большую разницу (потом ещё погоняю на пример1).
Я не заметил ничего подозрительного, циклы все время работали (ещё бы чудес не бывает), я только заметил, что на каждом шаге цикла while меняется значение min (там пересчёт ввиду удалённых данных), что соответственно влияет на проверку, может в этом дело ?

Упд. как и говорил - есть тонкость во флоатах.
Загнал пример пример1.хлс , и прогнал первый шаг вайла - всё норм, на втором шаге увидел "глюк", по вочесам значения равны, а выдаёт при сравнении фолс.
Последние два вочеса на картинке - обычно добавлены, а первые два спецом в свойствах вочеса настроены на флоатинг-поинт отображение, как говорится, найди 10 отличий.

Можно последовать совету, что я давал выше.
Изображения
Тип файла: png fp_surprise.png (10.6 Кб, 34 просмотров)

Последний раз редактировалось phomm; 21.01.2015 в 21:59.
phomm вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Защита от попадания дубликатов в TThreadlist Stertor Общие вопросы Delphi 17 13.11.2020 13:26
Исследования попадания точки в заданную область uHkBu3uTop Помощь студентам 2 19.01.2012 12:35
Алгоритм попадания точки в прямоугольный треугольник t2skler Помощь студентам 3 22.10.2011 01:57
Цикл с предусловием. ( цикл while) Цикл с постусловием. (цикл repeat ... until) Mr.User Помощь студентам 9 23.11.2007 01:34