Страницы: 1 2 вся ветка
Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.17;
Скачать: [xml.tar.bz2];




Вниз

Господи, да что ж делается-то?! 


Baz   (2001-12-26 10:21) [0]

Здравствуйте, мэтры!
ПОЧЕМУ после выполнения строки
for M:=-1000 to 1000 do
переменная М становится равна 2001, а, если изменить на
for M:=-100 to 1000 do
то 1101. М описана как integer. Я чего-то не знаю, или пора из компа бесов изгонять?!
Заранее спасибо за любые подсказки
Baz.



panov   (2001-12-26 10:28) [1]

После выполнения цикла переменная цикла имеет неопределенное значение.



Baz   (2001-12-26 10:43) [2]

Все происходит ВНУТРИ цикла, СРАЗУ после begin.



panov   (2001-12-26 10:46) [3]

А M у тебя какого типа?



gek   (2001-12-26 10:48) [4]

Во блин, специально у себя посмотрел ничего такого не происходит
for M:=-1000 to 1000 do
if m = 2001 then
showmessage("kuku")
после цикла м будет 1001
если у тебя изменяется, то значит в цикле ее меняшь



Nemeiss   (2001-12-26 10:54) [5]

Как саму М в цикле используеш?



Гриф   (2001-12-26 10:56) [6]

Это работа оптимизатора кода.
Если переменная цикла не используется в теле цикла, то тебе все равно, как она отсчитывается.

В примере gek (26.12.01 10:48) счетчик цикла используется в условии,
поэтому "безобразия" не проиходит.

Бесов можешь не изгонять. Удачи.



Lusha   (2001-12-26 10:57) [7]

А точка с запятой после DO не стоит случаем?



Alx2   (2001-12-26 11:00) [8]

for M:=-100 to 1000 do;
У меня выглядит как
@start:
mov ebx,$ffffff9c
inc ebx
cmp ebx,$3e9
jnz @start:
После цикла, в этом случае естественно, m = 1001.
Но предупреждение: в зависимости от оптимизации значение m не обязано быть равным 1001 полсе такого цикла. Есть множество причин этому.



Андрей Сенченко   (2001-12-26 11:42) [9]

НЕ ВЕРЮ
При прогоне примера значение M внутри цикла равно собственно тому, что насчиталось в for ... do, а на выходе из цикла - Верхняя граница + 1
Желающие могут запустить :


unit Unit1;

interface

uses
Windows, SysUtils, Controls, Forms, Buttons, StdCtrls, Classes;

type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
for i := StrToInt(Edit1.Text) to StrToInt(Edit2.Text) do
Label1.Caption := IntToStr(i);
Label2.Caption := IntToStr(i);
end;

end.



Андрей Сенченко   (2001-12-26 11:43) [10]

Ну то есть у меня не M а i



Anatoly Podgoretsky   (2001-12-26 11:47) [11]

Андрей Сенченко © (26.12.01 11:42)
Ну и что из того, что она у тебя Верхняя граница + 1



Anatoly Podgoretsky   (2001-12-26 11:48) [12]

Baz © (26.12.01 10:43)
Не может быть, обманываешь.



Виктор Щербаков   (2001-12-26 11:50) [13]

to Baz
Это следствие работы оптимизатора.
Если переменная цикла не используется внутри цикла, то компилятор/оптимизатор может поменять направление отсчета, начальное и конечное значения. Лишь бы количество выполнений зацикленного опреатора осталось прежним. Так что отключи оптимизацию и наслаждайся.

А о использовании переменных цикла сразу после его выполнения компилятор выдает предупреждение.



Андрей Сенченко   (2001-12-26 12:01) [14]

> Anatoly Podgoretsky ©
На трех машинах проверил. Из любопытства. Везде именно так. Но не в этом дело. Исходя из основной пробемы вопроса можно предположить, что у него на выходе из цикла в этой переменной содержится значение количества проходов цикла.
Но мне повторяю достичь такого результата не удалось. ( То самое "неопределенное№, которое:
[Warning] Unit1.pas(35): FOR-Loop variable "i" may be undefined after loop





Anatoly Podgoretsky   (2001-12-26 12:09) [15]

Ну и что из того, что ты проверил на трех машинах, ты проверь на разных компиляторах, например Д1 и Д5.
Предполагать можно, но Борланд говорит не нужно!



Андрей Сенченко   (2001-12-26 12:18) [16]

> Anatoly Podgoretsky ©
Резонно. Да ни к чему все это. Понятно, что можно найти компилятор, при ктором на выходе из цикла переменная уйдет вообще в минус бесконечность.
Но это все баловство по той простой причине, что вопрос:
Baz © (26.12.01 10:43)
>> Все происходит ВНУТРИ цикла, СРАЗУ после begin.

А вот это вот - совсем непонятно



Baz   (2001-12-26 12:18) [17]

Спасибо всем, особенно to Виктор Щербаков! Действительно, у меня М внутри цикла использовалась, а потом я это закомментировал. Поставил внутрь строку if M=0 then; и все нормализовалось. А как отключать этот оптимизатор? Или лучше его не трогать?



Alx2   (2001-12-26 12:32) [18]

Ctrl+Shift+F11/Compiler/Optimization

А зачем отключать? Разве что для стыковки ассемблера. Да и то очень редко... и только местами :))



Anatoly Podgoretsky   (2001-12-26 12:34) [19]

Андрей Сенченко © (26.12.01 12:18)
А чего тут непонятного, код приводить не хочет, значит оно ему нужно



Baz   (2001-12-26 15:20) [20]

Код длинный. Ну вот прямо сейчас гляжу на надпись: Variable Y inaccessible due to optimizatioin. Y у меня массив, по ходу цикла я вычисляю некоторые параметры с исп-ем эл-тов этого массива. Ну, типа
for I:=N-1 downto MAX_I do
begin
.........
A[I]:=Y[I]-C[I+1]+B[I]/2*DELTA-B[I+1]*X[I]-A[I+1]*IntPower(X[I],2);
.........
Все остальные массивы вижу, (в пошаговом прогоне) а Y - нет. За шаг до входа в цикл все виделось. Что еще? I, N, MAX_I - integer, N=9, MAX_I=2.
Это какие-то штучки оптимизатора или что-то еще?



Alx2   (2001-12-26 16:07) [21]

Оптимизатор выкинул из кода Y, так как Y далее не используется. Но из привиденного примера это не следует :). Видимо, причина где-то еще внутри цикла. Весь код можно посмотреть?



Anatoly Podgoretsky   (2001-12-26 17:08) [22]

Да все нормально, он его просто разместил в регистре



Alx2   (2001-12-26 17:13) [23]

Так вопрос, как я понял, в том, что массив в Watch не втыкается...



Anatoly Podgoretsky   (2001-12-26 19:24) [24]

Не может этого быть, должен втыкаться, вот показывать не обязан



SlavaG   (2001-12-26 20:22) [25]

Может я не по теме, но от -100 до +100 есть еще и 0-ноль



Anatoly Podgoretsky   (2001-12-26 22:02) [26]

Ну есть, в сумме составить 201 иттерацию.



Baz   (2001-12-27 06:43) [27]

Пока суд да дело, я уже код сто раз перепахал, но привожу весь нынешний текст подпрограммы. Вкратце суть задачи (вдруг, интересно :))
Х - массив узлов ф-и (Х=15, 20, 25.....)
Y - зн-я ф-и в узлах (не совсем, но можно считать, что так)
А,В,С - коэф-ты парабол, которыми и интерполирую ф-ю между узлами
N - число узлов, DELTA - шаг (т.е. здесь DELTA=5)
TARGET_AGE - целевая точка (напр., TARGET_AGE=23, Y(23)-?)
============================================
//ВЫЧИСЛЕНИЕ СПЛАЙН-ФУНКЦИИ И ПЛОЩАДЕЙ ФИГУР
procedure TMAIN_FRM.SPLAIN(X:T_ARRAY;var Y,A,B,C:T_ARRAY;
TARGET_AGE:real;DELTA,N:integer);
//T_ARRAY - задан в др. месте так:
//type T_ARRAY=array[0..21] of real;

var ETALON,MAX_Y:double;MAX_I,I,J:integer;
A_ETALON,B_ETALON,C_ETALON:T_ARRAY;
Y_SPLAIN:array[0..105] of real;
begin
A[N]:=3*Y[N]/IntPower(DELTA,2);
B[N]:=-6*Y[N]*X[N]/IntPower(DELTA,2);
C[N]:=3*Y[N]*IntPower(X[N],2)/IntPower(DELTA,2);
MAX_I:=2;
for I:=N-1 downto MAX_I do
begin//Расчет всех A, B, C
B[I]:=-10000;
ETALON:=999999999999;
repeat
B[I]:=B[I]+1;//Выч-ем параметры для функции Y_SPLAIN
A[I]:=Y[I]-C[I+1]+B[I]/2*DELTA-B[I+1]*X[I]-A[I+1]*IntPower(X[I],2);//Для простоты восприятия А выч-ся в два этапа
A[I]:=A[I]*3/
(IntPower(X[I-1],2)-2*IntPower(X[I],2)+X[I-1]*X[I]);
C[I]:=A[I+1]*IntPower(X[I],2)-A[I]*IntPower(X[I],2)+
B[I+1]*X[I]-B[I]*X[I]+C[I+1];
MAX_Y:=0;
for J:=0 to DELTA-1 do//Зн-я ф-и на I-м уч-ке
begin
Y_SPLAIN[I*DELTA-J]:=A[I]*IntPower((X[I]-J),2)+B[I]*(X[I]-J)+C[I];
if Y_SPLAIN[I*DELTA-J]<0
then MAX_Y:=MAX_Y+ETALON;
//Мне нужна минимальная сумма зн-ий ф-и Y_SPLAIN
MAX_Y:=MAX_Y+Y_SPLAIN[I*DELTA-J];
end;//of for J
if MAX_Y<ETALON then //Текущая ф-я лучше эталонной
begin
ETALON:=MAX_Y;//Запомним лучшие параметры
A_ETALON:=A;
B_ETALON:=B;
C_ETALON:=C;
end;//of смена эталона
until B[I]>=1000;
A:=A_ETALON;//Восстанавливаем лучшие параметры из эталонных
B:=B_ETALON;
C:=C_ETALON;//}
//!!!!!!!!!!
{ for J:=0 to DELTA-1 do//Зн-я ф-и на I-м уч-ке
Y_SPLAIN[I*DELTA+J]:=A[I+1]*IntPower((X[0]+I*DELTA+J),2)+B[I+1]*(X[0]+I*DELTA+J)+C[I+1];
Y_SPLAIN[N*DELTA]:=A[N]*IntPower(X[N],2)+B[N]*X[N]+C[N];//}
//!!!!!!!!!!!!!
end;//of for I
I:=1;
while X[I]<TARGET_AGE do I:=I+1; //В каком отрезке искомый возраст?
//Вычис-е площадей фигур под сплайн-функцией
//И вывод результатов
RSLT_LBL_1.Caption:="S= "+
FloatToStr(A[I]/3*(IntPower(X[I],3)-IntPower(X[I-1],3))+
B[I]/2*(IntPower(X[I],2)-IntPower(X[I-1],2))+
C[I]*(X[I]-X[I-1]));
RSLT_LBL_2.Caption:="S1 = "+
FloatToStr(A[I]/3*(IntPower(TARGET_AGE,3)-IntPower(X[I-1],3))+
B[I]/2*(IntPower(TARGET_AGE,2)-IntPower(X[I-1],2))+
C[I]*(TARGET_AGE-X[I-1]));
RSLT_LBL_3.Caption:="S2 = "+
FloatToStr(A[I]/3*(IntPower(X[I],3)-IntPower(TARGET_AGE,3))+
B[I]/2*(IntPower(X[I],2)-IntPower(TARGET_AGE,2))+
C[I]*(X[I]-TARGET_AGE));//}
end;//of begin
====================================
При входе в цикл по I в окне Watch Y исчезает до конца программы и появляется эта гнусная надпись про optimization. Но, обнаружено, что Y прекрасно видно, если раскомментировать выделенный !-ми участок. ДО входа в цикл Y видно. Что происходит?






Alx2   (2001-12-27 08:45) [28]

Сразу замечу: sqr(x) быстрее, чем IntPower(x,2).
Далее Y[i] - инвариант внутри цикла repeat...until. Вследствии чего, компилятор помнит значение Y[i] вчерез регистр ebp. Ее адрес (Y[i])на i-м шаге ebp-$2c. Регистр ebp инвариант в цикле repeat...until. Таким образом, имеет место регистровая оптимизация посему Y is inaccessible...

Чтобы наслаждаться Y-м в окне Watch:
Ctrl+Shift+F11/Compiler/Optimization - вырубить.
ПЕРЕКОМПИЛИРОВАТЬ проект (Project->Build)

После отладки включить оптимизацию.
Снова перекомпилировать.



Alx2   (2001-12-27 08:50) [29]

Сорри, очепятка :))
Вместо: "Ее адрес (Y[i])на i-м шаге ebp-$2c"
Следует читать: "Ее адрес (Y[i])на i-м шаге [ebp-$2c]."
Соответственно, уменьшение адреса на 8 происходит только лишь в конце цикла for I:=N-1 downto MAX_I do...



Labert   (2001-12-27 09:19) [30]

Эх вы, "мастера"!
Единственную разумную мысль на этой ветке высказал panov. За пределами цикла переменная цикла не определена. Придерживайтесь правил структурного программирования, товарищи!



Baz   (2001-12-27 09:23) [31]

Не буду врать, что все понял из предыдущего ответа, но метод борьбы уяснил, кажется. Спасибо!



Виктор Щербаков   (2001-12-27 09:26) [32]

Labert (27.12.01 09:19)
Хм...
И что же это за правила такие???



Alx2   (2001-12-27 09:32) [33]

Labert, собственно говоря, речь сейчас идет не о значении переменой после цикла, а о работе дебаггера на оптимизированном коде.

Ну а про значение переменной цикла за его пределами говорить даже не стоит. Согласен, нет этого значения в общем случае да и не нужно оно, если подумать...



Labert   (2001-12-27 09:36) [34]

To Виктор Щербаков
Ну это примерно то же самое, что и "хороший тон" в программировании. То есть - без Goto, и т.п. Если интересно, можно поискать в яндексе что-нибудь по структурному программированию.



ValeraVV   (2001-12-27 10:35) [35]

Структурное программирование ни при чем, если для организации for всего лишь нужно использовать регистр процессора, то зачем выделять под нее (переменную) память и обращаться к этой памяти каждый раз внутри цикла - оптимизатор действует нелогично? А логично выглядел бы ассемблерный код если бы все компилилось так как надо Baz © (26.12.01 10:21). Программа пишется всего один раз, и множество раз исполняется, что важнее?



Алексей Петров   (2001-12-27 10:55) [36]

> Андрей Сенченко © (26.12.01 11:42)
Твой пример кода по одному параметру не подходит под утверждение "Если переменная цикла не используется в теле цикла, то тебе все равно, как она отсчитывается.".

У тебя в цикле идет присвоение Label1.Caption := IntToStr(i); и компилятор себе вольностей позволить уже не может.
Сделай тело цикла пустым, например, и результат будет другим.




ValeraVV   (2001-12-27 11:10) [37]

Поясню (ValeraVV © (27.12.01 10:35)),
1.var
2. i:integer; //Объявили локальную переменную (Выделили память в стеке)
3.begin
4. for i:=0 to 100 do //1-ая итереция - Обнулили регистр, остальные - сверили значение регистра с 100
5. begin
6. Label1.Caption:=IntToStr(i); //для вызывая IntToStr передали ей значение регистра
7. end; // увеличили регистр
8.end;

По логике Baz © (26.12.01 10:21), где-то в строчке 6. надо было бы подставить в i (то есть в стек) значение регистра, затем для функции IntToStr подставить значение i (из стека), вопрос зачем?



ValeraVV   (2001-12-27 11:11) [38]

Поясню (ValeraVV © (27.12.01 10:35)),
1.var
2. i:integer; //Объявили локальную переменную (Выделили память в стеке)
3.begin
4. for i:=0 to 100 do //1-ая итереция - Обнулили регистр, остальные - сверили значение регистра с 100
5. begin
6. Label1.Caption:=IntToStr(i); //для вызывая IntToStr передали ей значение регистра
7. end; // увеличили регистр
8.end;


По логике Baz © (26.12.01 10:21), где-то в строчке 6. надо было бы подставить в i (то есть в стек) значение регистра, затем для функции IntToStr подставить значение i (из стека), вопрос зачем?



Alx2   (2001-12-27 11:23) [39]


Baz"у, конечно, виднее. Но я думаю, что все уперлось в то, что в дебаггере ему надо было видеть значения любых переменных. А оптимизация это не обеспечивает. Посему выход: временно ее отключить (на время отладки).

Кстати,в Microsoft Visual C++ есть конфигурации Release и Debug.
В Debug оптимизации практически нет и видны все переменные. Но если выбрать Release, то многие локальные переменные накрываются медным тазом (ясно, почему). И, поверьте, оптимизация в MVC много лучше, чем в Delphi.

Но я, например, пишу на Delphi из-за комфорта, а скоростные алгоритмы, если допечет, конечно, делаю на MVC (связка с Delphi-project через DLL).



Alx2   (2001-12-27 11:27) [40]

???



NUU   (2001-12-27 11:37) [41]

To nil ©
А я бы к такому и работать не пошел



nil   (2001-12-27 12:26) [42]

г-н МОДЕРАТОР, я думаю что, если бы молодой человек, затеявший эту дискуссию, не перепахивал свой код сто раз, а изначально разбил бы код на логические составляющие, то и не было бы всех этих страстей. А с точки зрения работодателя, мне нужен код читамый с одного взгляда, и если структура кода сделана правильно то я, в своей команде, могу закрыть глаза и на отсутсвие коментариев.



Alx2   (2001-12-27 12:30) [43]

>nil
Так ведь опыт - сын ошибок трудных :))



Baz   (2001-12-27 12:35) [44]

Во я спросил! Аж приятно, сколько копий ломается :). Раз уж разговор идет, продолжаю спрашивать. Я оптимизацию представляю весьма смутно. Что, вообще, произойдет плохого, если я ее отключу? Код сейчас не вспомню, но неколько раз натыкался на то, что не мог посмотреть значение I внутри цикла for I:=...... , если не вставлял в конце что-нибудь вроде If I>0 then; А частенько бывает нужно. А вот, к слову, только что набросал:

procedure TForm1.Button1Click(Sender: TObject);
var I,J:integer;
begin
J:=0;
for I:=0 to 10 do
J:=J+1;
if J>1 then;
end;
Здесь при проходе цикла I почему-то меняется от 11 до 1. Это имеет отношение к оптимизации?



gek   (2001-12-27 12:36) [45]

Во елки-моталки, из-за чего спрашивается такой базар развели?
Из-за чепухи.



Alx2   (2001-12-27 12:45) [46]

>Baz
Отключаешь оптимизацию и смотришь...
Плохого не произойдет. Только упадет скорость выполнения программы.
Если раздражает "непонятное" поведение переменных в отладчике - отключи оптимизацию. Когда все отладишь - включи ее и продавай прогу :)).
PS
Уже третий раз пишу про отключить/включить оптимизацию 8-(



VitHouse   (2001-12-27 12:47) [47]

var i: integer;
begin
i := 0;
for i := -100 to 100 do
begin
end;
caption := inttostr(i);//будет ровно 100
end;



Baz   (2001-12-27 14:03) [48]

to Alx2
Я уже отключил :). Но народ тут говорит, что она, вроде как, ничему не мешает. А зачем-то же она есть? Скомпилированный код меньше? Ну и я, собственно, продолжаю спрашивать, чтобы уже просто побольше узнать и, плюс, вдруг кто-нибудь про какие-нибудь грабли вспомнит?



Alx2   (2001-12-27 14:24) [49]

Оптимизация=выигрыш в скорости и/или в размере etc.
Обычно не используется при отладке и профилировании программы.
Обычно используется в подготовке релизов.

Вообще, смотря что подо что оптимизировать.
В Delphi оптимизация сбалансированная. Дает выигрыш в размере и скорости. Но есть и исключения.

Об этом можно говорить до бесконечности, см. литературу по компиляторам, архитектуре процессоров, их конвейерах, предсказателей ветвления и еще о множестве других наворотов.

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




Страницы: 1 2 вся ветка
Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.17;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.84 MB
Время: 0.043 c
14-52661          Beat                  2001-11-22 08:50  2002.01.17  
Я не понял в натуре, че за ДИСКРИМИНАЦИЯ???


1-52528           alexias               2001-12-27 14:54  2002.01.17  
Дерево каталогов просканировать


14-52650          paul_shmakov          2001-11-21 01:13  2002.01.17  
подсветка синтаксиса в форуме


1-52596           Вадим                 2001-12-29 21:29  2002.01.17  
PROMT


4-52684           Roman_                2001-11-16 23:00  2002.01.17  
Вывод многострочного текста под углом