Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Вниз

Компилятор насчитал 1+1=1. Почему? Привожу код:   Найти похожие ветки 

 
AAAlexeyAAA   (2004-06-13 19:55) [0]

type TPoint  = record
           X : longint;
           Y : longint;
          end;
type Tochka = record
           ArrayPoint : array of TPoint;
           Rastoyanie : array of integer;
          end;
var RecArray : Tochka;
Courses : array [1..8] of TPoint=((X:0;Y:-1),(X:1;Y:-1),(X:1;Y:0),(X:1;Y:1),(X:0;Y:1),(X:-1;Y:1),(X:-1;Y:0),(X:-1;Y:-1));
localpoint : TPoint;
begin
RecArray.ArrayPoint[0].X := 1;
RecArray.ArrayPoint[0].Y := 1;
for count:=Low(RecArray.ArrayPoint) to High(RecArray.ArrayPoint) do
 begin
  For count2:=1 to 8 do
    begin
localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X;
localpoint.Y := RecArray.ArrayPoint[count].Y + Courses[count2].Y;
------------------
На шаге count=0, count2=4 (координата:(1,1))
localpoint.X = 1, a localpoint.Y = 2. Почему?
Ставлю брейкпоинт. Первое слагаемое 1, второе тоже 1. Сумма =1
В чём проблема?


 
default ©   (2004-06-13 20:01) [1]

SetLength забыл


 
AAAlexeyAAA   (2004-06-13 20:04) [2]

есть...есть он...перед строкой
RecArray.ArrayPoint[0].X := 1;
.............
SetLength(RecArray.ArrayPoint,1);
SetLength(RecArray.Rastoyanie,1);

Проблема в том что он всё считает правильно, кроме координаты 1,1...
Весь перебор Courses верен,..кроме Courses[4]


 
default ©   (2004-06-13 20:11) [3]

type TPoint  = record
          X : longint;
          Y : longint;
         end;
type Tochka = record
          ArrayPoint : array of TPoint;
          Rastoyanie : array of integer;
         end;
         var

RecArray : Tochka;
Courses : array [1..8] of TPoint=((X:0;Y:-1),(X:1;Y:-1),(X:1;Y:0),(X:1;Y:1),(X:0;Y:1),(X:-1;Y:1),(X:-1;Y:0),(X:-1;Y:-1));
localpoint : TPoint;

 Form1: TForm1;
 count, count2: Integer
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(RecArray.ArrayPoint,1);
SetLength(RecArray.Rastoyanie,1);
RecArray.ArrayPoint[0].X := 1;
RecArray.ArrayPoint[0].Y := 1;
for count:=Low(RecArray.ArrayPoint) to High(RecArray.ArrayPoint) do
begin
 For count2:=1 to 4 do
   begin
localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X;
localpoint.Y := RecArray.ArrayPoint[count].Y + Courses[count2].Y;
end;
end;
Caption := IntToStr(localpoint.X)

end;

вот такой код 2 выводит...


 
AAAlexeyAAA   (2004-06-13 20:21) [4]

localpoint.X = 1 (1+1=1)
localpoint.Y = 0 (1+1=0)
:)


 
AAAlexeyAAA   (2004-06-13 20:28) [5]

Подскажите хоть "где копать" ?


 
default ©   (2004-06-13 20:30) [6]

выложи код полностью который работает неверно


 
AAAlexeyAAA   (2004-06-13 20:33) [7]

Прошу прощения <<default>>.
Если повесить на кнопку то работает. Всё правильно считает.
Но если изменить код моей программы...
с <<For count2:=1 to 8 do>> на
 <<For count2:=1 to 4 do>> то нет!!!


 
default ©   (2004-06-13 20:39) [8]

опять же [6]
что должно получиться?
а какая разница между этим
for count:=Low(RecArray.ArrayPoint) to High(RecArray.ArrayPoint) do
begin
For count2:=1 to 4 do
  begin
localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X;
localpoint.Y := RecArray.ArrayPoint[count].Y + Courses[count2].Y;
end;
end;
и этим
localpoint.X := RecArray.ArrayPoint[High(RecArray.ArrayPoint) ].X + Courses[4].X;
localpoint.Y := RecArray.ArrayPoint[High(RecArray.ArrayPoint) ].Y + Courses[4].Y;
?
смысл цикла?


 
AAAlexeyAAA   (2004-06-13 20:42) [9]

есть массив точек...[x,y]
мне нужно помотреть окружающие их точки на предмет нахождения в них 0 или 1


 
AAAlexeyAAA   (2004-06-13 20:44) [10]

procedure TForm1.StartGo(EP,SP : TPoint);
var localpoint : TPoint;    // вспомогательная переменная, для сокращ. записи
   count2,count : integer;
   SchetRast, addcount : integer;
begin
 If (EP.X = SP.X) and (EP.Y = SP.Y) then
   begin
     ShowMessage("Начальная и конечная точки совпадают");
     Exit;
   end;
   SetLength(RecArray.ArrayPoint,1);
   SetLength(RecArray.Rastoyanie,1);
   RecArray.ArrayPoint[0].X := SP.X;
   RecArray.ArrayPoint[0].Y := SP.Y;
   RecArray.Rastoyanie[0] := Distantion(SP);
   SchetRast := Distantion(SP);
    while Length(RecArray.ArrayPoint)<>0  do
      begin
      While Proverka(SchetRast)=true do
        begin
          for count:=Low(RecArray.ArrayPoint) to High RecArray.ArrayPoint) do
            begin
              If RecArray.Rastoyanie[count] = SchetRast then
                begin
                  For count2:=1 to 8 do
                    begin
If MapArray[RecArray.ArrayPoint[count].X + Courses[count2].X,
RecArray.ArrayPoint[count].Y + Courses[count2].Y] = 0 then   // если клетка равна 0
 begin
localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X;
localpoint.Y:= RecArray.ArrayPoint[count].Y + Courses[count2].Y;
If (localpoint.X = EP.X) and (localpoint.Y = EP.Y) then
                             begin
                             ShowMessage("NAydeno!!!");
                             break;
                             Exit;
end; {end If (localpoint.X = EP.X) and (localpoint.Y = EP.Y)}
{увелич массив на 1 элемент и записываем координаты точки и расстояние: от SP до EP через текущую точку}
SetLength(RecArray.ArrayPoint, Length(RecArray.ArrayPoint)+1);
RecArray.ArrayPoint[High(RecArray.ArrayPoint)].X := localpoint.X;
RecArray.ArrayPoint[High(RecArray.ArrayPoint)].Y := localpoint.Y;
SetLength(RecArray.Rastoyanie, Length(RecArray.Rastoyanie)+1);
RecArray.Rastoyanie[High(RecArray.Rastoyanie)] := Distantion(localpoint);
{изменяем 0 поля(карты) на расстояние: от SP до EP через текущую точку}
MapArray[localpoint.X, localpoint.X] := Distantion(localpoint);
end;{ End IF MapArray[RecArray.ArrayPoint[count].X + Courses[count2].X,RecArray.ArrayPoint[count].Y + Courses[count2].Y] = 0 }
                 end; { End For count2:=1 to 8 do}
             end;{ End If RecArray.Rastoyanie[count] =SchetRast}
             Inc(SchetRast);
move(RecArray.ArrayPoint[count+1], RecArray.ArrayPoint[count], ((High(RecArray.ArrayPoint)-count)*SizeOf(RecArray.ArrayPoint)));
end;{ End for count:=Low(RecArray.ArrayPoint) to High(RecArray.ArrayPoint)}
{ удаляем "отработанный" элемент массива}
      end;//While Proverka(SchetRast)=true do
     end; { End while Length(RecArray.ArrayPoint)<>0 }
ShowMessage("NE NAydeno!!!");
end;


 
Gero ©   (2004-06-13 20:45) [11]


> AAAlexeyAAA   (13.06.04 20:44

"О Боже мой! Стали мы совсем чужие..." (c) из песни


 
AAAlexeyAAA   (2004-06-13 20:46) [12]

может я закину весь проект...тебе на мыло...глянешь?


 
default ©   (2004-06-13 20:50) [13]

нееее!
вроде явных "промахов" не видно, так что смотри внимательней свой код
проверь один небольшой кусок кода, потом другой и тд. пока не найдёшь ошибку


 
AAAlexeyAAA   (2004-06-13 20:57) [14]

Почему на брейкпоинте каждое слагаемое равно 1, а сумма их равна 1, а не 2?


 
Piter ©   (2004-06-13 22:28) [15]

AAAlexeyAAA (13.06.04 20:57) [14]

у тебя исходники под D7? Заархивируй их (без exe файла) и кинь мне на piter007@newmail.ru
И скажи на какой строчке ошибка, то есть где ставить брекпоинт, чтобы аргументы были по 1, а сумма тоже 1
Мне очень интересно


 
Piter ©   (2004-06-14 14:32) [16]

AAAlexeyAAA (13.06.04 20:57) [14]

очень интересный случай! Видимо, ошибка в оптимизаторе Дельфовом...
Пока копаю дальше...


 
default ©   (2004-06-14 16:07) [17]

AAAlexeyAAA скинь на ___ALex___@inbox.ru
Piter ©   (14.06.04 14:32) [16]
вряд-ли...


 
Piter ©   (2004-06-14 16:24) [18]

AAAlexeyAAA (13.06.04 20:57) [14]

в общем, рассказываю. Конечно, компилятор не ошибся и оптимизация не ошибочна, но некие грабли здесь есть (для новичка, я думаю, очень страшные грабли).

У тебя есть цикл

For count2:=1 to 8 do
   begin
       If MapArray[RecArray.ArrayPoint[count].X + Courses[count2].X,
       RecArray.ArrayPoint[count].Y + Courses[count2].Y] = 0 then   // если клетка равна 0
           begin
               localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X;
               localpoint.Y := RecArray.ArrayPoint[count].Y + Courses[count2].Y;
               ...


Как должен выполняться данный цикл? Переменной Count2 присваивается значение 1, выполняется тело цикла. Потом Count2 присваивается 2 и опять выполняется тело цикла. И так до 8 или пока не прервешь цикл оператором Break.

И так оно и есть на самом деле, если ты отключишь оптимизацию "Project -> Options" (или SHIFT+CTRL+F11). Потом вкладка "Compiler" и галочка "Optimization". (после переключения галочки не забудь пересобрать проект, нажав "Project -> Build FindPath")

Но при включенной оптимизации цикл программно выполняется не так! Сначала Count2 присваивается значение 8 и выполняется тело цикла, потом 7, 6 и так до 1. То есть, цикл идет в обратную сторону. Но при этом, если идет обращение к счетчику Count2 внутри цикла, то подставляется "правильное" значение, как если бы цикл шел от 1 до 8.

Давай на примере. Допустим, при ВКЛЮЧЕННОЙ оптимизации значение счетчика Count2 = 6 (это как раз то значение, при котором первый раз будет выполнен if )
Как будет выполняться строка:

localpoint.X := RecArray.ArrayPoint[count].X + Courses[count2].X; ?

вовсе не так как ты думаешь! Да, Count2 равен 6. Но ведь включена оптимизация, и на самом деле в строчку будет вместо count2 подставлено число 3 (когда Count2 будет равен 5, то будет подставлено 4 и т.д.).
А проблема в том, что IDE Delphi этого не понимает. Программно все правильно, на третьей итерации тело цикла будет выполнено так, как будто значение счетчика равно 3 (хотя на самом деле Count2 = 6). При этом localpoint.X присвоится значение, равное RecArray.ArrayPoint[count].X (а это 1) плюс Courses[3].X (а это тоже 1). В результате получим 2 и все правильно!

Но если по брекпоинту смотреть на значение Courses[count2].X - то IDE покажет значение "-1", так как будет смотреть шестой элемент массива. Понимаешь? Компилятор знает, что он пустил цикл наоборот, от 8 до 1 и учитывает это при выполнении цикла. А IDE Delphi не учитывает, он видит, что Count2 равен 6, ну и показывает шестой элемент, он не знает, что идет только третья итерация.

Вот и получаются глюки. Если ты в WatchList занесешь выражение
RecArray.ArrayPoint[count].Y + Courses[count2].Y
то оно в WatchList будет равно нулю! А на самом деле компилятор в данной строчке посчитает его как 2! Вот такие забавности есть в Дельфи.

Во всем написанном ты можешь сам убедиться, поигравшись с флажком оптимизации (после переключения галочки не забудь пересобрать проект, нажав "Project -> Build FindPath").

Выход из данной ситуации - отлаживать приложение с выключенной оптимизацией, тогда никаких разногласий между IDE Delphi и компилятором не будет. А когда программа будет готова, то перед финальной сборкой включить оптимизацию (это повышает скорость выполнения программы и уменьшает ее объем).


 
Piter ©   (2004-06-14 16:32) [19]

И еще замечания по программе:

нафига ты объявляешь:

type TPoint  = record
           X : longint;
           Y : longint;
          end;


Тип TPoint и так уже объявлен в модуле Windows, который у тебя подключен


 
AAAlexeyAAA   (2004-06-14 22:43) [20]

Piter
Большое спасибо за помощь! Я догадывался, что дело в компиляторе,..точнее думал, что чего-то в директивах компилятора нужно делать...(добавлять+/удалять-).
Об том, что счётчик идёт наоборот я видел. Просто по сравнению с вопиющем 1+1=1, я на это закрыл глаза. (да и мне большой разницы то нет,...в каком порядке оно поедет: туда или обратно)
Но есть одно НО, к-рого я так и не понял!
1-ое: Далее по коду есть такая строка(от проблемной строки на 15 вниз, включая комементарии). Она ну никак не влияет на шаги циклов...где всё смешалось, мечи секиры, топоры....
Так вот, я немного ошибся, вместо:
MapArray[localpoint.X, localpoint.X] := Distantion(localpoint);
нужно записать
MapArray[localpoint.X, localpoint.Y] := Distantion(localpoint);
1. Вопрос первый. Почему после изменения ЭТОЙ строки. Всё работает без отключения оптимизации. (так я поборол проблему сложений 1+1)...:)


 
Piter ©   (2004-06-15 15:13) [21]

AAAlexeyAAA (14.06.04 22:43) [20]
Вопрос первый. Почему после изменения ЭТОЙ строки. Всё работает без отключения оптимизации


ты не прав. Изменение данной строки ничего не меняет. Но немного применив свои телепатические способности вот что хочу сказать. ТЫ УЧЕЛ МОИ ПРИМЕЧАНИЯ В СКОБОЧКАХ?
после переключения галочки оптимизации не забудь пересобрать проект, нажав "Project -> Build FindPath")
Ты это сделал? Наверняка, ты поставил галочку оптимизации и запустил тут же приложение (F9) - и ничего не изменилось. Программа запустилась такая же неоптимизированная. Чтобы изменения вступили в силу - надо сделать Build.

Не дай бог выяснится, что дело в этом. Потому что обидно - пишешь, пишешь примечания. А их все равно не читают... ты бы постарался вникнуть в каждое слово, написанное мной в предыдущем посте. Пусть у тебя уйдет час на это. Пусть день, зато поймешь. А ты небось по диагонали почитал, понял, что просто надо вырубить оптимизацию и успокоился....



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.047 c
14-1086719021
Vasya.ru
2004-06-08 22:23
2004.06.27
хороший чистильщик реестра


4-1084959583
Elysium
2004-05-19 13:39
2004.06.27
Как написать приложение используя WinAPI


6-1083794068
saNat
2004-05-06 01:54
2004.06.27
Outlook Express


1-1086936564
ancara
2004-06-11 10:49
2004.06.27
Как получить R,G,B из clBtnFace?


3-1086245351
stas
2004-06-03 10:49
2004.06.27
поле numeric и ADO





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский