Я уже некоторое время использую предоставляемую Intel функцию RNG, чтобы обеспечить себя случайностью с помощью написанной мной программы на C ++ / CLI.
Однако через некоторое время что-то поразиломне как то особенно подозрительно.Среди прочего я прошу случайное число от 1 до 4 и каждый раз записываю результат на бумаге.Вот результаты:
2, 3, 3, 2, 1, 3, 4, 2, 3, 2, 3, 1, 3, 2, 3, 1, 2, 4, 2, 2, 1, 2, 1, 3, 1, 3, 3, 3, 3.
Количество 1с: 6 Количество 2с: 9 Количество 3с: 12 Количество 4с: 2 Всего: 29
Мне действительно интересно, есть ли проблема с RNG от Intel, моим алгоритмом, методологией или чем-то еще?Или вы считаете, что смещение пока недостаточно велико?
Я использую Windows 10 Pro, мой процессор - Intel Core i7-4710MQ.Скомпилировано с VS2017.
Методология:
- Запустите командную строку Powershell
- Загрузите мою сборку с помощью
Add-Type -Path <mydll>
- Invoke
[rdrw.Random]::Next(4)
- Добавьте один к результату
Подробности, которые могут иметь значение: я не очень часто спрашиваю об этом числе, так что между розыгрышами проходит некоторое время, и обычно это происходит, когдаRNG не использовался в течение некоторого времени (по крайней мере, один час).
И да, это ленивый алгоритм, я не хотел беспокоить себя исключениями.
Алгоритм следующий:
#include <immintrin.h>
namespace rdrw {
#pragma managed(push,off)
unsigned long long getRdRand() {
unsigned long long val = 0;
while (!_rdrand64_step(&val));
return val;
}
#pragma managed(pop)
public ref class Random abstract sealed
{
public:
// Returns a random 64 bit unsigned integer
static unsigned long long Next() {
return getRdRand();
}
// Return a random unsigned integer between 0 and max-1 (inclusive)
static unsigned long long Next(unsigned long long max) {
unsigned long long nb = max - 1;
unsigned long long mask = 1;
unsigned long long draw = 0;
if (max <= 1)
return 0;
// Create a bitmask that's at least as big as the biggest acceptable value
while ((nb&mask) != nb)
{
mask <<= 1;
mask |= 1;
}
do
{
// Throw unnecessary bits
draw = Next() & mask;
} while (draw>nb);
return draw;
}
// return a random unsigned integer between min and max-1 inclusive
static unsigned long long Next(unsigned long long min, unsigned long long max) {
if (max == min)
return min;
if (max < min)
return 0;
unsigned long long diff = max - min;
return Next(diff) + min;
}
};
}
Спасибо за ваши идеи!