Генерация случайных чисел эффективно - PullRequest
1 голос
/ 26 ноября 2011

Как эффективно генерировать случайные числа?Каждый раз, когда программа случайных чисел загружается, она начинает выплевывать те же числа, что и раньше.(Я думаю, из-за квази природы генерации случайных чисел)Есть ли способ, что случайная генерация становится недетерминированной?добавление энтропии к генерации, когда число, генерируемое после загрузки, отличается от предыдущего.(случайный случайный, а не квазислучайный)Кроме того, скажем, диапазон такой генерации (m, n) такой, что nm = x, есть вероятность, что число, скажем, «p», появится в следующий раз после того, как x-1 были сгенерированы другие числа.Но следующая партия таких чисел х не будет такой же, как последовательность из последней.Пример: диапазон: 1,5.Поколение: 2,4,5,1,3 (1-е) 4,2,3,1,5 (2-е) ... одинаковые числа.Я из смущенного состояния ума написал это:

int num1 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;
int num2 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1;

здесь диапазон был (1440).но он все еще генерирует числа вне границ и нуля, и его частота тоже не так уж велика.Это код C # .NET.Почему так?Ваши ответы могут быть независимыми от языка / алгоритмическими / аналитическими.Заранее спасибо.

Ответы [ 5 ]

2 голосов
/ 26 ноября 2011

Очень немногие генераторы "случайных" чисел на самом деле являются случайными.Почти все являются псевдослучайными, следуя предсказуемой последовательности при запуске с тем же начальным значением .Многие генераторы псевдослучайных чисел (PRNG) получают свои начальные значения из даты и времени их первоначального вызова.Другие получают свои исходные данные из источника случайных данных, предоставляемых операционной системой, которые часто генерируются из внешних источников ( например, , движения мыши, действия клавиатуры).

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

См. http://msdn.microsoft.com/en-us/library/system.random.aspx для получения подробной информации о классе C # Random, но в основном он использует очень хорошо известный и уважаемый алгоритм и заменяет его датой и временем.

Чтобы ответить на вашключевой вопрос, просто используйте rand.Next(min, max+1), и вы всегда получите случайную последовательность чисел от min до max включительно.Последовательность будет одинаковой каждый раз, когда вы используете одно и то же семя.Но rand = new Random() будет использовать текущее время, и пока ваша программа вызывается с некоторым разделением во времени, они будут отличаться.

1 голос
/ 26 ноября 2011

Создание одной и той же последовательности снова и снова часто является функцией, а не ошибкой, если вы управляете ею.Создание повторяемой последовательности облегчает отладку.Если вы серьезно относитесь к желанию воспроизвести невоспроизводимую случайную последовательность, вы можете найти безопасный генератор случайных чисел с этим в качестве цели проектирования.Вы пометили свой вопрос C #, но, поскольку Java имеет http://docs.oracle.com/javase/1.4.2/docs/api/java/security/SecureRandom.html, а Windows API имеет http://en.wikipedia.org/wiki/CryptGenRandom, вы можете найти эквивалент в C #.

1 голос
/ 26 ноября 2011

«Заполнить» генератор случайных чисел, получив количество секунд с полуночи и затем передав его:

Random rand = new Random(secs);

Это все еще не генерирует совершенно случайные числа, но должно служить вашей цели.

0 голосов
/ 07 ноября 2017

Вы можете использовать хаотическую карту для генерации случайных чисел. Приведенный ниже код C ++ (GenRandRea) возвращает вектор случайного числа с использованием так называемой «карты тентов» (https://www.wikiwand.com/en/Tent_map).). ) в качестве входных данных итерационной карты. Различные начальные числа будут генерировать различные последовательности.

vector<double> GenRandRea(unsigned seed, int VecDim){
double x, y, f;
vector<double> retval;

x = 0.5*(abs(sin((double)seed)) + abs(cos((double)seed)));

for (int i = 0; i<(tentmap_delay + VecDim); i++) {
    if ((x >= 0.) && (x <= 0.5)) {
        f = 2 * tentmap_r * x;
    }
    else {
        f = 2 * tentmap_r * (1. - x);
    }

    if (i>=tentmap_delay) {
        y = (x*tentmap_const) - (int)(x*tentmap_const);
        retval.push_back(y);
    }
    x = f;
}
return retval;

}

с

const double tentmap_r = 0.75; //parameter for the tent map
const int tentmap_delay = 50; /*number of interactions in the tent map 
                              allowing for sorting */
const double tentmap_const = 1.e6; //constant for the tent map

VecDim - выходное векторное измерение. Идея состоит в том, чтобы выполнить итерацию как минимум (tentmap_delay + VecDim) и записать результат в retval (вектор двойных чисел).

Чтобы использовать этот код:

vector<double> val;

val = GenRandRea(2, 10);
for (int kk=0; kk<10;kk++){
    cout << setprecision(9) << val[kk] << endl;
}

который, например, будет производить:

0,767902586 0,848146121 0,727780818 0,408328773 0.88750684 0.83126026 0,253109609 0,620335586 0,569496621 0,145755069

Привет!

0 голосов
/ 26 ноября 2011

Я не очень знаком с C #.Но я не думаю, что эта проблема возникнет в Java, потому что конструктор по умолчанию класса Random использует начальное число, основанное на текущем времени и уникальный идентификатор счетчика. Ниже приведен код из java.util.Random класса.

private static volatile long seedUniquifier = 8682522807148012L;
public Random() { this(++seedUniquifier + System.nanoTime()); }

Если C # doesent поддерживает это сразу, вы можете использовать приведенный выше код для создания уникального начального числа каждый раз.

PS: обратите внимание, что, поскольку доступ к seedUniquifier не синхронизирован, дажехотя это изменчиво, существует небольшая вероятность того, что одни и те же семена используются для нескольких объектов Random.Из javadoc класса Random:

"Этот конструктор устанавливает начальное значение генератора случайных чисел в значение , весьма вероятно, отличающееся от любого другого вызова этого конструктора."

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...