Главная страница
    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]

???



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

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

Наверх




Память: 0.55 MB
Время: 0.004 c
3-52481
Дима
2001-12-14 19:38
2002.01.17
Как обойтись без BDE


14-52657
Polevi
2001-11-23 10:14
2002.01.17
Дежавю


1-52582
Sym
2001-12-19 16:06
2002.01.17
Народ помогите!!!!!!!!!!!!!! За ранее СПАСИБО


4-52691
ZserG
2001-11-18 02:47
2002.01.17
Как вставить инструментальную панель в Explorer?


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





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