Форум: "Основная";
Текущий архив: 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]???
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2002.01.17;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.005 c