Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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 вся ветка

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

Наверх




Память: 0.58 MB
Время: 0.004 c
4-52689
Вадим
2001-11-16 17:31
2002.01.17
Имя компьютера


14-52666
MJH
2001-11-18 13:56
2002.01.17
nVidia Drivers 21.88


7-52677
Pal-nod
2001-09-28 18:04
2002.01.17
Excel


1-52573
Lamok (real)
2001-12-28 23:23
2002.01.17
EStringlistError


3-52505
Кнопка
2001-12-09 15:07
2002.01.17
Поиск в базе





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский