Превращение случайного числа в детерминированный белый шум - PullRequest
2 голосов
/ 12 октября 2009

Мне нужно иметь возможность сгенерировать одно случайное число, а затем использовать это число, чтобы создать на лету теоретически бесконечно большую двумерную плоскость с логическими значениями. Мне нужна функция, которую я могу вызвать, которая является детерминированной с тремя входами (x, y и случайным начальным числом) и возвращает обратно псевдослучайный результат:

int r = random()
//...
var value_for_point = f(x,y,r);

Если бы я использовал эту функцию для заполнения массива 10x10 единицами и нулями, в идеале он выглядел бы так же, как и / если бы я запросил случайное значение для каждой ячейки по мере продвижения, т.е. Это не должно быть идеально - это не для статистического анализа. Мне просто нужно иметь возможность воссоздать массив, учитывая то же случайное число.

Я не могу просто запустить генератор случайных чисел по двум причинам. Во-первых, мне нужно, чтобы эта функция основывалась на х и у. Я могу вызвать эту функцию, чтобы заполнить массив между (0,0) и (10, 10), а затем запросить значения между (-10, -5) и (3,4). Во-вторых, у языка, который я использую, нет функции семени.

Я уверен, что есть или тривиальный способ сделать это, которого я не вижу, или есть что-то в области фракталов, которые могут мне помочь. Кто-нибудь знает, как это сделать?

Ответы [ 6 ]

2 голосов
/ 12 октября 2009

Я думаю, вы хотите Шум Перлина ?

1 голос
/ 13 октября 2009

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

Вы можете, например, использовать правило 30 для генерации этого.

1 голос
/ 12 октября 2009

Это не на 100% идеально, но как насчет использования стандартного алгоритма, такого как SHA1 или MD5? SHA1 выдает строку из 160 битов из любой символьной строки, и она более или менее случайна. Чтобы заполнить ваш логический массив 10x10, вам понадобятся только самые младшие 100 бит, которые должны быть почти случайными. Поскольку вы начинаете с известной базовой строки (любой длины) в качестве начального числа, ваши значения воспроизводимы.

Я не знаю, какой язык вы используете, но реализации SHA1 и MD5 доступны практически для каждой операционной системы.

0 голосов
/ 12 октября 2009

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

Тем не менее, ограничение в основном теоретическое. Для большинства практических целей вы можете ограничить размер плоскости в зависимости от размера, который может указать пользователь. Например, если x и y - это два 32-битных целых числа, то вам нужно только иметь возможность имитировать плоскость с длиной 2 ^ 32-1x2 ^ 32-1, которая long кратна бесконечности.

Учитывая то, что вы сказали о генераторе случайных чисел в вашей системе, есть вероятность, что вам нужно (или, по крайней мере, очень сильно захотеть) написать собственный генератор или использовать существующий в Интернете, который имеет достаточно длительный период. Если вы собираетесь использовать 32-битные координаты X и Y, вам нужен генератор с как минимум 64-битным периодом.

Отсюда все довольно просто: вы объединяете биты координат x, y примерно так же, как при создании линейного адреса, в любой другой двумерный массив, затем используете результат в качестве начального числа для PRNG и получаете результат.

0 голосов
/ 12 октября 2009

Просто используйте что-то простое, как

private static uint GetUint()
{
    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
    return (m_z << 16) + m_w;
}

и начальные значения m_z и m_w. Сделайте это для каждого, х и у.

0 голосов
/ 12 октября 2009

Мог бы помочь, если бы мы знали язык.

C # ...

static bool GetPixel(int seed, ushort x, ushort y)
{
    int randomSeed = (x << 16 | y) ^ seed;
    Random rnd = new Random(randomSeed); 
    /* if you just want a constant result you can seed the function 
       on app start and never touch the random generator again */
    return rnd.NextDouble() >= .5;
}
...