Возможно ли получить чрезвычайно быстрый, но надежный (тот же вход = тот же выход, поэтому я не могу использовать время) генератор псевдослучайных чисел? Я хочу, чтобы конечный результат был чем-то вроде float NumGen(int x, int y, int seed);
, так что он создает случайное число от 0 до 1 на основе этих трех значений. Я нашел несколько генераторов случайных чисел, но я не могу заставить их работать, а генератор случайных чисел, который поставляется с Unity, очень медленный. Я должен сделать около 9 вызовов генератора на 1 метр поверхности, поэтому мне все равно, если это не является статистически статистически случайным, просто он работает очень быстро. Кто-нибудь знает об алгоритме, который соответствует моим потребностям? Спасибо :)Произвольный генератор случайных чисел
ответ
Я думаю, вам нужно было создать Случайный случай при каждом звонке NumGen. Чтобы функция возвращала один и тот же номер для тех же параметров, вы можете использовать хеш-функцию.
Я протестировал несколько вещей, и этот код был примерно в 3 раза быстрее, чем воссоздающие события Случайные.
//System.Security.Cryptography
static MD5 hasher = MD5.Create();
static byte[] outbuf;
static byte[] inbuf = new byte[12];
static float floatHash(uint x, uint y, uint z) {
inbuf[0]= (byte)(x >> 24);
inbuf[1]=(byte)(x >> 16);
inbuf[2]=(byte)(x >> 8);
inbuf[3]=(byte)(x);
inbuf[4]=(byte)(y >> 24);
inbuf[5]=(byte)(y >> 16);
inbuf[6]=(byte)(y >> 8);
inbuf[7]=(byte)(y);
inbuf[8]=(byte)(z >> 24);
inbuf[9]=(byte)(z >> 16);
inbuf[10]=(byte)(z >> 8);
inbuf[11]=(byte)(z);
outbuf = hasher.ComputeHash(inbuf);
return ((float)BitConverter.ToUInt64(outbuf, 0))/ulong.MaxValue;
}
Другой метод, использующий некоторые методы RSA примерно в 5 раз быстрее, чем нового System.Random (семена):
static uint prime = 4294967291;
static uint ord = 4294967290;
static uint generator = 4294967279;
static uint sy;
static uint xs;
static uint xy;
static float getFloat(uint x, uint y, uint seed) {
//will return values 1=> x >0; replace 'ord' with 'prime' to get 1> x >0
//one call to modPow would be enough if all data fits into an ulong
sy = modPow(generator, (((ulong)seed) << 32) + (ulong)y, prime);
xs = modPow(generator, (((ulong)x) << 32) + (ulong)seed, prime);
xy = modPow(generator, (((ulong)sy) << 32) + (ulong)xy, prime);
return ((float)xy)/ord;
}
static ulong b;
static ulong ret;
static uint modPow(uint bb, ulong e, uint m) {
b = bb;
ret = 1;
while (e > 0) {
if (e % 2 == 1) {
ret = (ret * b) % m;
}
e = e >> 1;
b = (b * b) % m;
}
return (uint)ret;
}
Я побежал тест, чтобы генерировать 100000 поплавков. Я использовал индекс как семя для System.Random и как параметр x floatHash (y и z был 0).
System.Random: Min: 2.921559E-06 Max: 0.9999979 Повторы: 0
floatHash MD5: Min: 7.011156E-06 Max: 0.9999931 Повторения: 210 (значения возвращали дважды)
GetFloat RSA: Min: 1.547858E-06 Max: 0.9999989 Повторы: 190
Вы уверены, что результат RANDOM? Все, что я вижу, это то, что вы хешируете массив байтов и деля результат на ulong.maxvalue? Как это должно быть случайным? –
Это не совсем случайно. Я отредактировал отчет об испытаниях в ответ. – schwer
Это кажется совершенным, но у меня проблемы с его использованием. Я использую Unity, и по какой-то причине происходит сбой при каждом запуске. Я не думаю, что он любит uint, потому что я пытался общаться с ними раньше, и это заняло очень много времени. Есть ли способ преобразовать его в единственное int, потому что я не уверен, как работает код, а битовые операторы зависят от длины бит. –
Я думаю, что вы недооцениваете System.Random
класс. Это довольно быстро. Я считаю, что ваше замедление связано с созданием нового экземпляра класса Random
при каждом вызове вашего метода NumGen
.
В моем быстром испытании я смог генерировать 100 000 случайных чисел, используя System.Random
примерно за 1 миллисекунду.
Чтобы избежать замедления, рассмотрите точки посева в 2D-плоскости. Распределите точки посева так, чтобы они покрывали расстояние не более 100 000 метров. Затем сопоставьте (или вычислите) ближайшую начальную точку для каждого счетчика и используйте эту точку в качестве вашего семени до System.Random
.
Да, вы будете генерировать тонну случайных чисел, которые вы никогда не будете использовать, но они практически бесплатны.
Псевдо-код:
double NumGen(x, y, distance, seed) {
Random random = new Random(seed);
double result = 0;
for (int i=0; i<distance; i++) {
result = random.NextDouble();
}
}
Вы можете изменить эту простую схему, чтобы вернуть последовательность случайных чисел (возможно, представляющих собой сетку), и пара, что с механизмом кэширования. Это позволит вам сохранить память и улучшить (уменьшить) потребление ЦП.
- 1. Произвольный генератор случайных чисел с использованием предубежденного
- 2. Генератор случайных чисел Выпуск
- 3. Генератор случайных смежных чисел
- 4. Генератор случайных чисел Java
- 5. Неисправный генератор случайных чисел?
- 6. Генератор случайных чисел
- 7. java генератор случайных чисел
- 8. Verilog Генератор случайных чисел
- 9. генератор случайных чисел
- 10. Генератор случайных чисел
- 11. Генератор случайных чисел
- 12. Генератор случайных чисел
- 13. Треугольные генератор случайных чисел
- 14. Генератор случайных чисел Python
- 15. Генератор случайных чисел Crossplatform
- 16. Генератор случайных чисел Haskell
- 17. Генератор случайных чисел MATLAB
- 18. Генератор случайных чисел андроида
- 19. Генератор случайных чисел Boost
- 20. Генератор случайных чисел
- 21. Истинно генератор случайных чисел
- 22. GUI Генератор случайных чисел
- 23. Требуется генератор случайных чисел
- 24. Генератор генераторов случайных чисел
- 25. arc4random Генератор случайных чисел
- 26. Node.js генератор случайных чисел?
- 27. генератор случайных чисел C++
- 28. Генератор псевдослучайных случайных чисел
- 29. Генератор распределенных случайных чисел
- 30. генератор случайных чисел, android
Да, это возможно. Линейный конгруэнц-генератор - это две строки кода. –
Я бы посмотрел в поколение System.Random.Он использует время, но если вы поменяете это время на свое семя или даже объедините два, вы получите то, что, я думаю, вы здесь описываете. –
@EricLippert Я не могу найти прочь, чтобы реализовать линейный конгруэнц-генератор, чтобы принимать 3 входа и работать 0f-1f. –