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




Вниз

Генератор случайных числе 


cranium   (2002-03-31 00:25) [0]

Требуется получит последовательность случайных чисел, для этого использую Randomize и Random. При отладке все работает нормально, но когда запускю откомпилированный файл выдается последовательность в которой одно число повторяется два раза подряд, к примеру: 5,5, 12,12, 66,66 ........... Что делать чтоб этого не было?



Malder   (2002-03-31 00:36) [1]

Странно. Если ты делаешь так:

Randomize;
i:=Random;

То все должно работать на Ура...



cranium   (2002-03-31 08:43) [2]

Именно так и делаю. Да кстати это началось после смены проца с 650 на 900 Атлон.И еще все корретно работало только под Windows 2000 server, под 95/98/МЕ те же грабли........



Anatoly Podgoretsky   (2002-03-31 10:04) [3]

cranium © (31.03.02 08:43)
Ошибка в 17 строке.



cranium   (2002-04-01 09:06) [4]

Поясни, ты о чем?



MBo   (2002-04-01 09:13) [5]

о том, что без кода нечего обсуждать



Anatoly Podgoretsky   (2002-04-01 11:03) [6]

О том, что в 17 строке твоей программы есть ошибка.



PVOzerski   (2002-04-01 11:18) [7]

Зря иронизируете, IMHO, источник проблемы виден и без кода. Автор вопроса не хочет, чтобы сгенеренная
последовательность не содержала повторяющихся чисел, а стандартная функция random этого не
обеспечивает. Простейший по алгоритму (но не самый быстрый) способ лечения - просматривать все
предыдущие значения после вызова random и вызывать random до тех пор, пока полученное число не будет
уникальным. Остальное - на совести алгоритма генерации псевдослучайных чисел.



mrcat   (2002-04-01 11:28) [8]

Если ты все это делаешь в цикле, то объявляй рандомайз до цикла, IMHO лучше делать в разделе initialize... т.к. тик системного таймера < скорости работы цикла...
//
Randomize;
for i := 1 to n do begin
j:=Random;
// всякие действия с j
end;



Reindeer Moss Eater   (2002-04-01 13:11) [9]

cranium>
Последовательность, содержащая повторяющиеся числа не перестает быть случайной.

Тебе, видимо, на самом деле нужна не просто псевдослучайная последовательность.

Если это надо для утилиты, формирующей списки экзаменационных билетов, то сначала объяви множество целых длиной = кол-ву вопросов в билете. После генерации очередного случ. числа проверь есть ли оно в множестве. Если нет - ты получил очередной номер вопроса для билета (занеси при этом его в множество). Если есть - повтори генерацию числа снова.
B и так далее



Anatoly Podgoretsky   (2002-04-01 13:17) [10]

Такую последовательность как приведена генератор не может выдать, ошибка в коде



Alx2   (2002-04-01 13:30) [11]

>После генерации очередного случ. числа проверь есть ли оно
>в множестве. Если нет - ты получил очередной номер вопроса
>для билета (занеси при этом его в множество).
>Если есть - повтори генерацию числа снова.
Чем меньше осталось билетов, тем больше приходится ждать :(
Есть (правда ничтожный, но есть) шанс, что будем ждать следующего номера, например, 10 минут.



MBo   (2002-04-01 13:46) [12]

>последовательность как приведена генератор не может выдать

может, если над ним так надругаться
for i := 1 to n do begin
Randomize; // а надо 1 раз до цикла или при иниц. программы
// делать, как mrcat написал
j:=Random;
// всякие действия с j
end;



Anatoly Podgoretsky   (2002-04-01 13:52) [13]

Ну так речь и идет о том, что у него ошибка в 17 строке



reonid   (2002-04-01 13:56) [14]

отобрази оставшиеся числа диапазона 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));



Alx2   (2002-04-01 14:10) [15]

>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 можно еще где-нибудь..



handra   (2002-04-01 16:17) [16]

А зачем городить что-то, может просто написать реализацию конгруэнтного датчика ПСЧ - его алгоритм построен на том, что в полученная последовательность содержит уникальные числа (т.е. при встрече числа, уже присутствующего, последлвательность повторяется)?



Alx2   (2002-04-01 16:24) [17]

>handra © (01.04.02 16:17)
Не слышал об этом. Подробнее можно?



handra   (2002-04-01 17:27) [18]

Линейный конгруэнтный генератор псевдослучайных чисел (ПСЧ). Выглядит так: Tn+1 = ((A*Tn) + C) mod M,
где:
A - множитель, такой, что (A mod 4)=1, т.е., например,5,9,13...
С - коэффициент, должен быть нечетным.
М - модуль, должен быть степенью двойки, например, 8,16,32,64...
Т0 - "порождающее число" - может быть любым целым.
Все эти условия должны быть обязательно выполнены. Генератор выдает псевдослучайную последовательность в диапазоне 0..М, причем каждое число встречается только один раз.



Poirot   (2002-04-01 20:19) [19]

Люди!!! Открываем книжку (том 2 ИП на ЭВМ)господина Кнута и и создаём вполне работоспособный ГСЧ... но скорее ГПСЧ... алгоритмы там расписаны...



Anakin   (2002-04-01 23:23) [20]

Случайная последовательность "лепится" с использование системных часов. Так что, если твой комп слишком быстр, то значения получаются одинаковые. Попробуй использовать таймер с малой задержкойю



Alx2   (2002-04-02 07:34) [21]

>handra © (01.04.02 17:27
Ага, ясно. Обычные вычеты...
>Poirot © (01.04.02 20:19)
>и создаём вполне работоспособный ГСЧ... но скорее ГПСЧ
А чем random не устраивает? "Качество" рапределения у него для большинства приложений достаточное.
>Anakin (01.04.02 23:23)
>Случайная последовательность "лепится"
>с использование системных часов.
>Так что, если твой комп слишком быстр,
>то значения получаются одинаковые.
>Попробуй использовать таймер с малой задержкойю
Это верно для randomize. Random использует переменную RandSeed для генерации следующего числа. Скорость процессора (квант таймера) в этом случае не влияет.



MBo   (2002-04-02 07:56) [22]

IMHO, автору ничего уже не надо. на форуме он ночью появлялся, а кода так и не привел. Наверно, нашел ошибку и исправил.



Alx2   (2002-04-02 08:03) [23]

>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;



Anatoly Podgoretsky   (2002-04-02 13:48) [24]

Все таки он трижды появился, но как только запросили исходники сразу слинял, или стыдно или сверх секретная программа.




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




Наверх





Память: 0.77 MB
Время: 0.035 c
1-46298           Эдуард                2002-03-31 17:08  2002.04.15  
Как получить резальтат работы внешней программы


1-46437           LazyCat               2002-04-02 17:04  2002.04.15  
Как сделать липкие формы?


14-46518          phantom2040           2002-03-06 15:10  2002.04.15  
Округление в Delphi


1-46334           Mikel Fryg            2002-04-02 22:25  2002.04.15  
Как сделать форму активной?


3-46257           Makc                  2002-03-25 17:52  2002.04.15  
Почему она пишет field w is an unknown type?