Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.02.2010, 19:51   #1
InternetStranger
php / delphi
Форумчанин
 
Аватар для InternetStranger
 
Регистрация: 10.06.2007
Сообщений: 175
Хорошо Обращение к предыдущему/следующему элементу массива по его адресу.

Прошу помочь разобраться.

Предыстория вопроса:
Значит, есть у меня массив двумерный (of real), площадью > 1e6.
В рекурентной формуле интенсивно пользуюсь его элементами.
Поскольку читаю его последовательно, то можно оптимизировать обращение к массиву. (Определить указатель, и читать как из файла, смещая указатель)
Простейший пример реализации этого алгоритма:

Код:
	var
   u : array[1..10] of real;

Type
    TRealPointer = ^real;

procedure TForm1.Button1Click(Sender: TObject);
var
   i          : integer;
   s          : string;
   my_pointer : TRealPointer;   // указатель на участок памяти длиной 8 байт
begin
     // Тестовые данные в массив
     for i:=1 to 10 do u[i]:= 0.1*i;

     // типы двойной точности "real" имеют в памяти размер 8 байт.
     // массив - это последовательное расположение в памяти этих блоков - элементов- в данном случае по 8 байт
     my_pointer := @u; // или так @u[1]; // запишем адрес начала массива
                       // доступ к значению в памяти, на которое сейчас указывает указатель - через "разыменование" указателя my_pointer^ 

     // выведет первый элемент массива 
     label2.Caption := FloatToStr( my_pointer^ );

     // а теперь распечатаем весь массив:
     // чтобы получить адрес след. элемента массива u[i+1], скажем из адреса элемента u[i], нужно задать смещение на длину блока,
     // в данном случае на 8 байт:  " @u[i] + $08 " (след. элемент)   ; " @u[i] - $08 " (пред. элемент)
     s:= '';
     for i:=1 to 10 do begin
         s:= s + FloatToStr( my_pointer^ ) + '  |  ';
         inc(my_pointer,$01); // -> сдвигаем указатель вправо к след. элементу  (на 8 байт) . вот эта строка преобразуется всего в одну ассемблерную строчку, потому нужно ЯВНО указывать смещение: либо число, либо константу (НЕ типизированную)
     end;
     // выведет весь массив
     label4.Caption := s ;
end;
Видно, что указатель my_pointer в пределах i-й итерации указывает на область памяти, содержащую значение u[i]

Собственно вопрос:
Внутри цикла, на i-й итерации, необходимо обратиться к трем элементам u[i-1], u[i], u[i+1].
Не могу сообразить как указать явно указать смещение вперед/назад относительно my_pointer.
Охота что-то вроде my_pointer-$08, my_pointer, my_pointer+$08 чтобы эти конструкции можно было подставить в одно выражение
(Требуется извлечь максимальную эффективность! )
Можно, конечно, определить дополнительную переменную и получится что-то вроде

Код:
     ...
     for i:=2 to 9 do begin
	 prev_ptr:= my_pointer; 
	 next_ptr:= my_pointer;
	 inc(next_ptr); dec(prev_ptr);
         s:= s + FloatToStr( my_pointer^ ) + '  |  Сумма окрестностных элементов '+ FloatToStr( prev_ptr^ + next_ptr^ );
         inc(my_pointer,$01); // -> сдвигаем указатель вправо к след. элементу  (на 8 байт) . вот эта строка преобразуется всего в одну ассемблерную строчку, потому нужно ЯВНО указывать смещение: либо число, либо константу (НЕ типизированную)
     end;
     ...
end;
Но тут целых две операции присваивания, да еще инкрейз/декрейз. Что-то не нравится мне. проще (и может быть даже быстрее) обращаться к элементу массива
Работа с указателями, конечно, у Дельфина довольно специфична
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.
InternetStranger вне форума Ответить с цитированием
Старый 08.02.2010, 22:00   #2
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

Возможно, так подойдет:
Код:
  S := S + FloatToStr( TRealPointer(Cardinal(my_pointer) - 8)^ ) +
              FloatToStr( my_pointer^ ) +
              FloatToStr( TRealPointer(Cardinal(my_pointer) + 8)^ );
maxionans вне форума Ответить с цитированием
Старый 09.02.2010, 00:17   #3
InternetStranger
php / delphi
Форумчанин
 
Аватар для InternetStranger
 
Регистрация: 10.06.2007
Сообщений: 175
По умолчанию

Спасибо )) Отличный способ. Все как положено - жесткое приведение типов. Не мог сообразить, к какому же типу нужно привести указатели ))

Изучаю соответствующий ассемблерный код

Кста, а почему Cardinal-то ? Это из каких-то соображений, или просто так?
Он вроде переменной длины?
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.

Последний раз редактировалось InternetStranger; 09.02.2010 в 00:24.
InternetStranger вне форума Ответить с цитированием
Старый 09.02.2010, 02:39   #4
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

Цитата:
Кста, а почему Cardinal-то ? Это из каких-то соображений, или просто так?
Да, из соображений того, что Cardinal - это четырехбайтовый целочисленный тип без знака, каким и должен быть указатель в IA32.

Цитата:
Он вроде переменной длины?
Что значит "переменной длины"?
maxionans вне форума Ответить с цитированием
Старый 09.02.2010, 08:04   #5
InternetStranger
php / delphi
Форумчанин
 
Аватар для InternetStranger
 
Регистрация: 10.06.2007
Сообщений: 175
По умолчанию

Да это я глупость какую-то прочитал на сайте одном. не так понял.
Цитата:
Тип Cardinal это тип целых чисел, чей размер не гарантирован, базовый беззнаковый целый тип в Delphi, и на настоящий момент он имеет тот же размер, что и LongWord: 32 бита.
И щас не понимаю, что это значит.
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.
InternetStranger вне форума Ответить с цитированием
Старый 09.02.2010, 10:11   #6
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

Это они видимо говорят о том, что, когда выйдет delphi, способная генерировать код для 64-битной архитектуры, в ней Cardinal может стать 8-байтовым целочисленным типов без знака.
maxionans вне форума Ответить с цитированием
Старый 10.02.2010, 20:44   #7
InternetStranger
php / delphi
Форумчанин
 
Аватар для InternetStranger
 
Регистрация: 10.06.2007
Сообщений: 175
По умолчанию

Протестировал на скорость выполнения.
К сожалению, компилятор не правильно понимает, чего от него хотят (может я просто не так спрашивал)).

В любом случае, следующий способ хоть и не очень удобен, но явно эффективнее:

Код:
 
...
my_pointer:= @u[i];
prev_ptr:= my_pointer; 
next_ptr:= my_pointer;
inc(next_ptr); dec(prev_ptr);

for i:=2 to 9 do begin
         s:= s + FloatToStr( my_pointer^ ) + '  |  Сумма окрестностных элементов '+ FloatToStr( prev_ptr^ + next_ptr^ );
         inc(my_pointer); inc(next_ptr); inc(prev_ptr);
end;
...
Т.е. хоть и приходится поддерживать 3 указателя (не шибко эстетично), но за то явно указано, по какому адресу обратиться )

PS: За предложенный алгоритм тоже спасибо.
maxionans.reputacia.inc(+1);
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.
InternetStranger вне форума Ответить с цитированием
Старый 10.02.2010, 23:12   #8
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

А можно поинтересоваться отчего такая щепетильность к оптимизации выполнения? У вас там гигабайты обрабатываемых данных или же вы пишете для калькулятора?
maxionans вне форума Ответить с цитированием
Старый 11.02.2010, 01:28   #9
InternetStranger
php / delphi
Форумчанин
 
Аватар для InternetStranger
 
Регистрация: 10.06.2007
Сообщений: 175
По умолчанию

из "калькуляторов" уже давно вырос ))
вот собственно моя задача Статья

Под скромненькой фразой во введении "С помощью численных методов рассмотрена..." кроется многолетняя борьба за каждый такт, за каждый квант процессорного времени )) И все во имя отечественной науки.

вот это тоже ради нее
G.Azamat { Web Development / Computer simulation }
Начинающий программист думает, что в килобайте 1000 байтов, а законченный уверен, что в километре 1024 метра.
InternetStranger вне форума Ответить с цитированием
Старый 11.02.2010, 06:35   #10
maxionans
Форумчанин
 
Аватар для maxionans
 
Регистрация: 02.01.2010
Сообщений: 254
По умолчанию

нет, я про калькулятор говорил не в том смысле, что вы создаете программу-калькулятор, а в том, что компьютер, для которого вы пишите, по производительности сравним с калькулятором.
maxionans вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
обращение к элементам двумерного массива на С++ серг Помощь студентам 16 05.12.2009 21:01
обращение к элементу таблицы в WebBrowser nikola86 Общие вопросы Delphi 13 14.11.2009 00:55
Получить массив B, присвоив его k-му элементу значение 0, если все элементы [Pascal] М@лышка Помощь студентам 10 12.10.2009 23:29
STL обращение к элементу list sht0p0r Общие вопросы C/C++ 1 05.07.2009 21:22
Обращение из формы в dll к элементу главной формы (delphi) a_n_n_a Помощь студентам 3 10.05.2009 04:00