![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Генератор случайных числе [D3, D6]
cranium © (2002-03-31 00:25:00)Требуется получит последовательность случайных чисел, для этого использую Randomize и Random. При отладке все работает нормально, но когда запускю откомпилированный файл выдается последовательность в которой одно число повторяется два раза подряд, к примеру: 5,5, 12,12, 66,66 ........... Что делать чтоб этого не было?
Anatoly Podgoretsky (2002-04-02 13:48:00) [1]Все таки он трижды появился, но как только запросили исходники сразу слинял, или стыдно или сверх секретная программа.
Alx2 (2002-04-02 08:03:00) [2]>MBo © (02.04.02 07:56)
Скорее всего :)
Но если уж лезть в дебри по самые уши, то вот, на всякий случай, доказательство независимости random от таймера (randomize, естетственно, к этому не относится):
procedure _RandInt;
asm
{ ->EAX Range }
{ <-EAX Result }
IMUL EDX,RandSeed,08088405H
INC EDX
MOV RandSeed,EDX
MUL EDX
MOV EAX,EDX
end;
procedure _RandExt;
const two2neg32: double = ((1.0/$10000) / $10000); // 2^-32
asm
{ FUNCTION _RandExt: Extended; }
IMUL EDX,RandSeed,08088405H
INC EDX
MOV RandSeed,EDX
FLD two2neg32
PUSH 0
PUSH EDX
FILD qword ptr [ESP]
ADD ESP,8
FMULP ST(1), ST(0)
end;
MBo (2002-04-02 07:56:00) [3]IMHO, автору ничего уже не надо. на форуме он ночью появлялся, а кода так и не привел. Наверно, нашел ошибку и исправил.
Alx2 (2002-04-02 07:34:00) [4]>handra © (01.04.02 17:27
Ага, ясно. Обычные вычеты...
>Poirot © (01.04.02 20:19)
>и создаём вполне работоспособный ГСЧ... но скорее ГПСЧ
А чем random не устраивает? "Качество" рапределения у него для большинства приложений достаточное.
>Anakin (01.04.02 23:23)
>Случайная последовательность "лепится"
>с использование системных часов.
>Так что, если твой комп слишком быстр,
>то значения получаются одинаковые.
>Попробуй использовать таймер с малой задержкойю
Это верно для randomize. Random использует переменную RandSeed для генерации следующего числа. Скорость процессора (квант таймера) в этом случае не влияет.
Anakin (2002-04-01 23:23:00) [5]Случайная последовательность "лепится" с использование системных часов. Так что, если твой комп слишком быстр, то значения получаются одинаковые. Попробуй использовать таймер с малой задержкойю
Poirot (2002-04-01 20:19:00) [6]Люди!!! Открываем книжку (том 2 ИП на ЭВМ)господина Кнута и и создаём вполне работоспособный ГСЧ... но скорее ГПСЧ... алгоритмы там расписаны...
handra (2002-04-01 17:27:00) [7]Линейный конгруэнтный генератор псевдослучайных чисел (ПСЧ). Выглядит так:
Tn+1 = ((A*Tn) + C) mod M,
где:
A - множитель, такой, что (A mod 4)=1, т.е., например,5,9,13...
С - коэффициент, должен быть нечетным.
М - модуль, должен быть степенью двойки, например, 8,16,32,64...
Т0 - "порождающее число" - может быть любым целым.
Все эти условия должны быть обязательно выполнены. Генератор выдает псевдослучайную последовательность в диапазоне 0..М, причем каждое число встречается только один раз.
Alx2 (2002-04-01 16:24:00) [8]>handra © (01.04.02 16:17)
Не слышал об этом. Подробнее можно?
handra (2002-04-01 16:17:00) [9]А зачем городить что-то, может просто написать реализацию конгруэнтного датчика ПСЧ - его алгоритм построен на том, что в полученная последовательность содержит уникальные числа (т.е. при встрече числа, уже присутствующего, последлвательность повторяется)?
Alx2 (2002-04-01 14:10:00) [10]>reonid © (01.04.02 13:56)
Или так: :)
Type TIntegerArray = array [0..MaxSize-1] of integer;
Function GetVal(Var myArray: TIntegerArray; var CurrentSize: Integer): Integer;
Var
idx: Integer;
Begin
idx := random(CurrentSize);
Result := myArray[idx];
myArray[idx] := myArray[CurrentSize - 1];
dec(CurrentSize);
End;
Чтобы особо не загромождать, следить за выполнением CurrentSize>0 можно еще где-нибудь..
reonid (2002-04-01 13:56:00) [11]отобрази оставшиеся числа диапазона 0..N-1 в непрерывный диапазон 0..M-1 и ищи случайное число в лиапазоне 0..M-1.
Можно, например, хранить целые в TList:
for i := 0 to N-1 do List.Add(Pointer(i));
i := Random(List.Count);
Result := Integer(List[i]);
List.Remove(Pointer(Result));
Anatoly Podgoretsky (2002-04-01 13:52:00) [12]Ну так речь и идет о том, что у него ошибка в 17 строке
MBo (2002-04-01 13:46:00) [13]>последовательность как приведена генератор не может выдать
может, если над ним так надругаться
for i := 1 to n do begin
Randomize; // а надо 1 раз до цикла или при иниц. программы
// делать, как mrcat написал
j:=Random;
// всякие действия с j
end;
Alx2 (2002-04-01 13:30:00) [14]>После генерации очередного случ. числа проверь есть ли оно
>в множестве. Если нет - ты получил очередной номер вопроса
>для билета (занеси при этом его в множество).
>Если есть - повтори генерацию числа снова.
Чем меньше осталось билетов, тем больше приходится ждать :(
Есть (правда ничтожный, но есть) шанс, что будем ждать следующего номера, например, 10 минут.
Anatoly Podgoretsky (2002-04-01 13:17:00) [15]Такую последовательность как приведена генератор не может выдать, ошибка в коде
Reindeer Moss Eater (2002-04-01 13:11:00) [16]cranium>
Последовательность, содержащая повторяющиеся числа не перестает быть случайной.
Тебе, видимо, на самом деле нужна не просто псевдослучайная последовательность.
Если это надо для утилиты, формирующей списки экзаменационных билетов, то сначала объяви множество целых длиной = кол-ву вопросов в билете. После генерации очередного случ. числа проверь есть ли оно в множестве. Если нет - ты получил очередной номер вопроса для билета (занеси при этом его в множество). Если есть - повтори генерацию числа снова.
B и так далее
mrcat (2002-04-01 11:28:00) [17]Если ты все это делаешь в цикле, то объявляй рандомайз до цикла, IMHO лучше делать в разделе initialize... т.к. тик системного таймера < скорости работы цикла...
//
Randomize;
for i := 1 to n do begin
j:=Random;
// всякие действия с j
end;
PVOzerski (2002-04-01 11:18:00) [18]Зря иронизируете, IMHO, источник проблемы виден и без кода. Автор вопроса не хочет, чтобы сгенеренная
последовательность не содержала повторяющихся чисел, а стандартная функция random этого не
обеспечивает. Простейший по алгоритму (но не самый быстрый) способ лечения - просматривать все
предыдущие значения после вызова random и вызывать random до тех пор, пока полученное число не будет
уникальным. Остальное - на совести алгоритма генерации псевдослучайных чисел.
Anatoly Podgoretsky (2002-04-01 11:03:00) [19]О том, что в 17 строке твоей программы есть ошибка.
MBo (2002-04-01 09:13:00) [20]о том, что без кода нечего обсуждать