LINUX.ORG.RU

Перестал работать Randomize в Free Pascal

 


0

1

Debian Sid. Раньше работало, я это точно помню. Теперь же я получаю одинаковые числа в рамках одного сеанса работы написанной мною программы. Ради проверки я загрузился с флэшки где установлена работоспособная (и главное нетронутая!) версия Debian, там такая же история. То есть дело либо в коде либо в железе.

Вот код в котором я обнаружил проблему:

{var InputString:STRING;
var LengthNewString:BYTE;}

Function RandomChar:BYTE;
BEGIN
Randomize;
RandomChar:=Random(94)+33;
{RandomChar:=chr(Random(94)+33);}
END;

{Function RandomString(StringLength:BYTE):STRING;
BEGIN
RandomString:='';
FOR StringLength:=StringLength DOWNTO 1
DO
  BEGIN
  RandomString:=RandomString + RandomChar;
  END;
END;}


BEGIN
Randomize;
{writeln('Введите строку:');
read(InputString);

IF Length(InputString)=255
THEN 
 BEGIN
 writeln('Невозможно сделать более длинную строку, ибо исходная строка итак уже максимальной длины.');
 halt;
 END;
LengthNewString:=Length(InputString)+1;}

writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
writeln(RandomChar);
END.


Randomize разве не один раз должен вызываться?

А вообще переходи на C или Python.

EXL ★★★★★ ()

Это лишнее. Нет никакого оправдания выбору паскаля сегодня. Судя по коду могу предложить питон. Да и батареек там не в пример больше.

anonymous ()

Убрать Randomize из функции RandomChar.

bormant ★★★★★ ()
Ответ на: комментарий от EXL

Ограничения на один раз нет, но это не избавляет о необходимости понимать, что именно делает вызов — инициализирует seed значением таймера.
Одинаковый seed — одинаковое следующее полученное псевдослучайное число.
Одинаковый seed — все вызовы уложились в единицу времени :-), радоваться надо борзодействию :-)

bormant ★★★★★ ()

Сведения про максимальную длину строки в 255 байт сильно устарели, см. {$H+}, HugeString.

bormant ★★★★★ ()

Возможно, есть смысл

function RandomStr(len: Byte): String;
begin
  SetLength(Result,len);
  for len:=1 to len do Result[i]:=RandomChar;
end;

bormant ★★★★★ ()
Ответ на: комментарий от EXL

А вообще переходи на C или Python.

Всему своё время.

Randomize разве не один раз должен вызываться?

Да, один раз. Я применил его два раза чисто от отчаяния.

roboq6 ()
Ответ на: комментарий от bormant

Спасибо, помогло!

Но только почему Randomize внутри функции во-первых мешал Randomize в основном теле программы, а во-вторых ничего толком не делал если его «конкурента» в теле программы не было?

roboq6 ()
Ответ на: комментарий от bormant

Спасибо, я как раз ломал голову как использовать ansistring.

roboq6 ()
Ответ на: комментарий от anonymous

Судя по коду могу предложить питон.

Что значит «судя по коду»? Что в моём коде такого?

Да и батареек там не в пример больше.

Что ещё за «батарейки»?

roboq6 ()
Ответ на: комментарий от roboq6

Да, один раз. Я применил его два раза чисто от отчаяния.

Ты Randomize изначально применял потому что не в том месте.

Но только почему Randomize внутри функции во-первых мешал Randomize в основном теле программы, а во-вторых ничего толком не делал если его «конкурента» в теле программы не было?

Тебе же выше объяснили, что в твоём случае инициализацию генератора псевдорандомных чисел нужно выполнять один раз, сразу после запуска программы (после Begin). Ты же выполнял её каждый раз при вызове функции.

$ cat Random.c 
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int getRandomNumber(void) {
    srand(time(0));
    return rand() % 100 + 1;
}

int main(void) {
    srand(time(0));
    int i = 0;
    for (; i < 10; ++i) printf("%d\n", getRandomNumber());
    return 0;
}
$ gcc Random.c 
$ ./a.out 
14
14
14
14
14
14
14
14
14
14
$ cat Random.c 
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int getRandomNumber(void) {
//  srand(time(0));
    return rand() % 100 + 1;
}

int main(void) {
    srand(time(0));
    int i = 0;
    for (; i < 10; ++i) printf("%d\n", getRandomNumber());
    return 0;
}
$ gcc Random.c 
$ ./a.out 
31
28
57
42
34
58
93
95
68
45

Так понятно?

EXL ★★★★★ ()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от roboq6

Но только почему Randomize внутри функции во-первых мешал Randomize в основном теле программы

Рискну предположить, что randomize инициализирует генератор на основании системного времени. Соответственно, если вызовы функции достаточно близки друг к другу, после каждого получаем одну и ту же последовательность.

JaneDoe ()
Ответ на: комментарий от roboq6

Но только почему Randomize внутри функции во-первых мешал Randomize в основном теле программы, а во-вторых ничего толком не делал если его «конкурента» в теле программы не было?

ГПСЧ, ключевое слово «псевдо», и начало первому шагу дает Randomize, в зависимости от времени.

Комп работает быстро и время за несколько вызовов не меняется, потому и первое число после Randomize одно и то же, и так у тебя после каждого Randomize...

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от roboq6

Ты его 8 раз применил. Каждый раз при вызове, низя так. Только в начале работы программы один раз надо.

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

Ах вот оно что. То есть комп брал seed на основе системного времени и потом находил от этого seed первое число, но так как вызовы происходили быстро, то системное время не успевало измениться, seed получался одинаковый, и как следствией первое (и по совместительству последнее) число от каждого seed получалось одинаковым.

roboq6 ()
Ответ на: комментарий от roboq6

Этот фрагмент и для коротких строк работает. Для длинных, если не нужно ограничиваться 255 байтами на строку, поменять Byte на приличествующий случаю тип.

bormant ★★★★★ ()
Ответ на: комментарий от roboq6

Randomize; { This way we generate a new sequence every time the program is run}

все твои рандомайсы запитались одним и тем же значением текущего времени

anonymous ()
Ответ на: комментарий от roboq6

Что ещё за «батарейки»?

Не обращай внимания, тут просто есть люди, которые от паскаля испытывают боль и страдания, и стремятся ему всячески отомстить. Нормальный язык, в нём, например, в отличии от C++, полноценные модули есть.

// Сам пишу на С++, в целом не жалуюсь, но если бы Lazarus/FPC были бы готовы для нормальной работы году так в 2003-2005, возможно, сейчас бы я писал на них. Да и вообще, разница между современными ОО-языками сильно преувеличена рассказами тех, кто не осилил хотя бы пару из них.

hobbit ★★★★★ ()
Последнее исправление: hobbit (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.