5. ОБЛАСТИ ПРИМЕНЕНИЯ
СЛУЧАЙНЫХ ЧИСЕЛ
• Моделирование различных процессов, основанных
на случайных числах
• Автоматизированная генерация уникального
контента
• Реализация вариативности поведения в играх и
приложениях
5
7. ТРЕБОВАНИЯ К ГЕНЕРАТОРАМ
ПСЕВДОСЛУЧАЙНЫХ ЧИСЕЛ
• Длинный период
• Эффективность
• Портируемость
• Скорость получения последовательности
• Воспроизводимость
Джон фон Нейман
Всякий, кто питает слабость к
арифметическим методам
получения случайных чисел грешен
вне всяких сомнений
7
8. ПОВТОРЯЕМЫЕ
СЛУЧАЙНЫЕ ЧИСЛА
• Общий для всех контент
• Генерация контента на лету
• Сохранение конкретного контента в виде «зерна»
Что нам даёт повторяемость?
8
14. ВИЗУАЛИЗАЦИЯ
ПОСЛЕДОВАТЕЛЬНОСТЕЙ
Для визуализации будем использовать первые
3 байта полученного числа
14
Random (C#)
numbers 0..n seed 0
private static uint GetBytePart(uint i, int byteIndex)
{
return ((i >> (8 * byteIndex)) % 256 + 256) % 256;
}
public static Color GetColor(uint i)
{
float r = GetBytePart(i, 0) / 255f;
float g = GetBytePart(i, 1) / 255f;
float b = GetBytePart(i, 2) / 255f;
return new Color(r, g, b);
}
15. ВИЗУАЛИЗАЦИЯ
ПОСЛЕДОВАТЕЛЬНОСТЕЙ
15
Так же нам интересно координатное
представление сгенерированных чисел
После чего мы из 1 вычитаем отношение
значения cords[x,y] к max и преобразуем в
текстуру.
Random (C#)
numbers 0..n seed 0
var max = 0;
for (var i = 0; i < ints.Length; i += 2)
{
var x = GetBytePart(ints[i], ByteIndex);
var y = GetBytePart(ints[i + 1], ByteIndex);
var value = coords[x, y];
value++;
max = Mathf.Max(value, max);
coords[x, y] = value;
}
17. ЛИНЕЙНЫЙ КОНГРУЭНТНЫЙ
ГЕНЕРАТОР (LCG)
17
Деррик Генри, Лемер
1949
LCG
numbers 0..n seed 0
LCG
0th number seed 0..n
const long randMax = 4294967296;
state = 214013 * state + 2531011;
state ^= state >> 15;
return (uint) (state % randMax);
18. RANDU
18
RANDU
numbers 0..n seed 0
Само его название - RANDU
способно вызвать испуг в
глазах и спазмы в желудке у
многих учёных,
специализирующихся на
компьютерах
Парк Миллер
1960
const long randMax = 2147483648;
state = 65539 * state + 0;
return (uint) (state % randMax);
19. XorShift
19
XorShift
numbers 0..n seed 0
XorShift
0th number seed 0..n
Джордш Марсалья
2003
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
return state;
20. ВИХРЬ МЕРСЕННА
Макото Мацумото
Такудзи Нисимура
1997
20
MersenneTwister 64
numbers 0..n seed 0
MersenneTwister 64
0th number seed 0..n
ulong x;
if (mti >= NN)
{
// generate NN words at one time
for (var i = 0; i < NN - MM; i++)
{
x = (mt[i] & UM) | (mt[i + 1] & LM);
mt[i] = mt[i + MM]
^ (x >> 1) ^ MAG01[(int) (x & 0x1L)];
}
for (var i = NN - MM; i < NN - 1; i++)
{
x = (mt[i] & UM) | (mt[i + 1] & LM);
mt[i] = mt[i + (MM - NN)]
^ (x >> 1) ^ MAG01[(int) (x & 0x1L)];
}
x = (mt[NN - 1] & UM) | (mt[0] & LM);
mt[NN - 1] = mt[MM - 1]
^ (x >> 1) ^ MAG01[(int) (x & 0x1L)];
mti = 0;
}
x = mt[mti++];
x ^= (x >> 29) & 0x5555555555555555L;
x ^= (x << 17) & 0x71d67fffeda60000L;
x ^= (x << 37) & 0xfff7eee000000000L;
x ^= x >> 43;
return x;
21. 21
Unity Random
numbers 0..n seed 0
Unity Random
0th number seed 0..n
Unity Random
100th number seed 0..n
UNITY RANDOM
26. СЛУЧАЙНЫЕ ХЕШ ФУНКЦИИ
26
MD5
numbers 0..n seed 0
var hash = new Hash(0);
var rn0 = hash.GetHash(0);
var rn1 = hash.GetHash(1);
var rn2 = hash.GetHash(12);
var rn3 = hash.GetHash(13, 5);
var rn4 = Hash.GetHash(0, 0);
var rn5 = Hash.GetHash(0, 1);
var rn6 = Hash.GetHash(0, 12);
var rn7 = Hash.GetHash(0, 13, 5);
27. ГЕНЕРАТОР НА ОСНОВЕ ХЕШ
ФУНКЦИИ
27
class HashRandom
{
private int seed;
private int counter;
public HashRandom(int seed)
{
this.seed = seed;
}
public uint Next()
{
return Hash.GetHash(seed, counter++);
}
}
31. ОПТИМИЗАЦИЯ ХЕШ ФУНКЦИИ
А зачем? А почему?
31
• Хеш функции реализуются для задач свёртки сообщений
• На вход хеш функциям при генерации случайных чисел чаще всего подаются
простые целые числа, а не массивы данных
32. ОПТИМИЗАЦИЯ ХЕШ ФУНКЦИИ
32
1. Перевести обработку данных с типа byte, на тип int
2. Убрать функцию включения хвоста
3. Избавиться от конвертации массива byte в одно число int
33. xxHash
33
uint h32;
var index = 0;
var len = buf.Length;
if (len >= 16)
{
var limit = len - 16;
var v1 = seed + P1 + P2;
var v2 = seed + P2;
var v3 = seed + 0;
var v4 = seed - P1;
do
{
v1 = SubHash(v1, buf, index);
index += 4;
v2 = SubHash(v2, buf, index);
index += 4;
v3 = SubHash(v3, buf, index);
index += 4;
v4 = SubHash(v4, buf, index);
index += 4;
} while (index <= limit);
h32 = Rot32(v1, 1) + Rot32(v2, 7) + Rot32(v3, 12) + Rot32(v4, 18);
}
else
{
h32 = seed + P5;
}
h32 += (uint) len;
while (index <= len - 4)
{
h32 += BitConverter.ToUInt32(buf, index) * P3;
h32 = Rot32(h32, 17) * P4;
index += 4;
}
while (index < len)
{
h32 += buf[index] * P5;
h32 = Rot32(h32, 11) * P1;
index++;
}
h32 ^= h32 >> 15;
h32 *= P2;
h32 ^= h32 >> 13;
h32 *= P3;
h32 ^= h32 >> 16;
return h32;
Важное криптографическое свойство для шифрования, которое означает, что изменение значения малого количества битов во входном тексте или в ключе ведет к «лавинному» изменению значений выходных битов шифротекста. Другими словами, это зависимость всех выходных битов от каждого входного бита.
Получаем хеш следующего шага
Получаем хеш следующего шага
Частоиспользуемые функции MurMur3 У WangHash статистические показатель не очень, но любую функцию можно прогнать через себя 2 раза и получить более лучшие показатели