Не посылайте в FAQ, плз. Я там была. Конкретно по этой теме там пару слов
Только начала разбираться, и уже появилось несколько камней преткновения.
Условие. Необходимо создать СМО с ожиданием из 10 элементов, где: - время прибытия и время обслуживания - случайные числа с нормальным распределением (просто random не подходит) - остальные компоненты просчитываются, но об этом позже - соблюдается принцип очереди FIFO в динамике
Код (это не все, только то, что вызывает вопросы):
type TPClient=^TClient; {описание элементов очереди} TClient=record t1:real; {время прибытия} t2:real; {время ожидания} next:TPClient; end; var head,node:TPClient; naf: boolean; nay: real; {процедура вывода на экран} procedure Print1; var curr:TPClient; n:integer; begin curr:=head; while (curr<>NIL)do begin writeln(curr^.t1,' ',curr^.t2); curr:=curr^.next; end; end; {функция генерирования случайных чисел по закону норм.распределения} function nrandom:real; {вопрос 1} var u1,u2:real; begin naf:=not naf; if naf then nrandom:=nay else begin repeat u1:=random; until u1>0; u1:=sqrt(-2*ln(u1)); u2:=random*pi*2; nay:=u1*cos(u2); nrandom:=u1*sin(u2); end; end; {создание очереди} procedure Queure; var node:TPClient; curr:TPClient; pred:TPClient; n:integer; begin n:=0; naf:=true; while n<10 do begin new(node); node^.t1:=nrandom; node^.t2:=nrandom; {вопрос 3} curr:=head; pred:=NIL; while (curr<>NIL) and (node^.t1>curr^.t1) do {вопрос 2} begin pred:=curr; curr:=curr^.next; end; if pred=NIL then begin node^.next:=head; head:=node; end else begin node^.next:=pred^.next; pred^.next:=node; end; n:=n+1; end; end;
begin Queure; Print1; readln; end.
Вопросы: 1. Во всех алгоритмах норм.распределения генерируемые числа - вещественные, а мне необходимы целые. Плюс - числа должны быть >=0. Как грамотно их преобразовать? 2. В первой колонке сформированых чисел, по-моему, должен быть порядок - этот пришел в 0-ой момент времени, этот в 1-ый и т.д. Во второй - упорядочивание не должно проводиться. Как разобраться с этим? 3. Во второй колонке не должен попадаться 0 (время обслуживания не может быть таковым). Достаточно ли просто прибавить 1? И самый главный вопрос. После прогона получаются ОДИНАКОВЫЕ наборы чисел! Мне необходимо отразить результаты нескольких прогонов, а какой с них толк, если они одинаковые!
Помогите разобраться
Автор: Бродяжник 26.07.2006 17:29
Если идет речь о нормально распределенных случайных числах, то они ведь распределены на каком-то интервале, верно? Итак, имеем Fi - очередное сгенерированное Вашей функцией вещественное случайное число. Видимо, оно будет в интервале от 0 до 1? Или, в общем случае, от F1 до F2. TPi - очередное время прибытия. Тоже, надо полагать в некотором интервале - от TP1 до ТP2. TOi - очередное время обслуживания. В некотором интервале - от TО1 до ТО2. Тогда
Код
TPi := TP1 + (TP2-TP1)*(Fi-F1)/(F2-F1); TOi := TO1 + (TO2-TO1)*(Fi-F1)/(F2-F1);
Если Fi лежит в интервале от 0 до 1, тогда формулы упрощаются.
Код
TPi := TP1 + (TP2-TP1)*Fi; TOi := TO1 + (TO2-TO1)*Fi;
Если нужны именно целые числа (integer), то результат вычислений округляем (TPi := round(...)). По поводу наборов чисел. Поскольку Ваша функция случайных чисел использует стандартный random, то перед каждым прогоном один раз вызываем процедуру randomize - и будет счастье.
Автор: Jill 26.07.2006 19:23
Так, с этим разобралась Спасибо Кст, отдельное спасибо за randomize - вылетело из головы
Тут другой вопрос возник. Динамика. Что-то я с ней никак подружиться не могу
Как грамотно при закрытии проги уничтожать очередь, чтоб мусора не оставалось?
Автор: volvo 27.07.2006 21:52
Цитата(Jill @ 26.07.2006 15:23)
Как грамотно при закрытии проги уничтожать очередь, чтоб мусора не оставалось?
Наверное, так:
procedure Clear; var curr, deleting: TPClient; begin curr := head; while curr <> nil do begin deleting := curr; dispose(deleting); curr := curr^.next; end; head := nil; end;
begin writeln('before: ', memavail); { Проверяем: доступная память в начале работы }
Queure; Print1; Clear; { <--- Очищаем очередь }
writeln('after: ', memavail); { Доступная память после удаления очереди } readln; end.
Автор: Jill 28.07.2006 17:13
Ок, с мусором разобрались. Спасибо
Тут еще вопрос возник. Переписала процедуру построения очереди - мне кажется, предыдущая версия (вставка элементов в упорядоченный список) была мухляжом
Так честнее:
procedure Queure; var node:TPClient; n:integer; F1,F2:real; begin n:=0; naf:=true; while (n<10) do begin {вроде, можно тут поменять, но ведь node еще не создан...} new(node); F1:=nrandom; F2:=nrandom; curr:=head; pred:=NIL; while (curr<>NIL) do begin pred:=curr; curr:=curr^.next; end; if pred=NIL then begin node^.next:=head; head:=node; node^.t1:=Abs(round(F1)); end else begin node^.next:=pred^.next; pred^.next:=node; node^.t1:=Abs(round(F1))+pred^.t1; end; n:=n+1; node^.t2:=Abs(round(1+(10-1)*(F2-1)/(10-1)))+1; end; end;
Суть вопроса. По-моему, я ошиблась в условии - работа системы ограничена во времени, а не по количеству требований. Получается, система должна работать 10 единиц времени (без учета задержки из-за последнего требования). То бишь, до момента, когда node^.t1=10. Как организовать этот цикл? По-моему, repeat в динамике нельзя использовать...?
И еще один глупый вопрос (не ругайте, мне и так стыдно ). Как прервать работу программы при зацикливании?
Автор: volvo 28.07.2006 17:49
Цитата(Jill @ 28.07.2006 13:13)
По-моему, repeat в динамике нельзя использовать...?
Это почему? В смысле, почему ты думаешь, что Repeat нельзя, а While - можно? Кстати, даже если ты не хочешь переделывать цикл на Repeat, то всегда можно сделать так:
while naf do begin ... naf := (node^.t1 < 10) { Как только node^.t1 станет = или больше 10, цикл прервется на следующей итерации } end;
Цитата(Jill @ 28.07.2006 13:13)
Как прервать работу программы при зацикливании?
В смысле, как программно определить зацикливание и выйти из цикла, или у тебя запущенная программа зациклилась, и ты хочешь прервать ее работу?
P.S.
Цитата(Jill @ 28.07.2006 13:13)
Так честнее:
Еще честнее было бы не бегать все время по очереди, а сделать в TClient ссылку не только на Next, но и на Prev...
Автор: Jill 28.07.2006 17:59
Цитата
Это почему? В смысле, почему ты думаешь, что Repeat нельзя, а While - можно?
Понятия не имею... Один препод (не по этому предмету...фух ) почему-то жутко ругается на repeat в динамике. Это не так, да?
Цитата
В смысле, как программно определить зацикливание и выйти из цикла, или у тебя запущенная программа зациклилась, и ты хочешь прервать ее работу?
Второе - какими кнопками прервать
Цитата
Еще честнее было бы не бегать все время по очереди, а сделать в TClient ссылку не только на Next, но и на Prev...
volvo, это больной вопрос Они мне снятся уже, эти динамические переменные!!! Я уже не знаю, с какой стороны подойти, чтоб не обжечься...
Автор: volvo 28.07.2006 18:15
Цитата(Jill @ 28.07.2006 13:59)
Это не так, да?
Не так, конечно... Применять или нет Repeat/Until программист должен НЕ там, где используются (или не используются) динамические переменные, а там, где это удобно...
Цитата(Jill @ 28.07.2006 13:59)
Второе - какими кнопками прервать
Иногда помогает Ctrl+Break, но это срабатывает в Турбо-Паскале 7.0 далеко не всегда, а только во время выполнения операций ввода/вывода... В остальное время вряд ли у тебя получится что-то сделать...
Цитата(Jill @ 28.07.2006 13:59)
volvo, это больной вопрос Они мне снятся уже, эти динамические переменные!!! Я уже не знаю, с какой стороны подойти, чтоб не обжечься...
Если ты готова пожертвовать 4-мя байтами памяти на каждый элемент очереди, чтобы было проще (и быстрее, насколько я понимаю) работать с этой самой очередью, то добавь ссылку на предыдущий элемент. Если программа критична к использованию памяти, а скорость ее работы менее важна - то этого делать не стОит... А ошибаться не бойся: "Не ошибается только тот, кто ничего не делает" (С)
Автор: Jill 28.07.2006 19:50
Еще вопрос. По поводу вывода требований и течения смоделированного времени +это самое время, правда поединично надо тоже выводить (0,1,2,3,.....10)
Вывод списка требований производится с задержкой, если предыдущий и текущий элемент отличаются:
if (pred<>NIL)and(pred^.t1<>curr^.t1) then Delay(1000);
Как обработать данные, чтобы, например, если элементы отличаются на 2 - единицы времени - задержка вывода списка - в два раза больше {с этим вроде разобралась...}, а вывод текущего времени - продолжается? {а вот с этим - нет }