Perl 28/13 ≈ 2,15
sub r{$s^=~($s^=$s/7215)<<8}
файл журналу тут
Perl 29/13 ≈ 2,23
sub r{$s^=~($s^=$s<<8)/60757}
файл журналу тут
Вони є чимось варіацією на Xorshift , використовуючи поділ з плаваючою точкою замість правого зсуву. Вони обидва проходять 13 з 15 тестів, не виконавши лише тестів 6 та 7.
Я не точно впевнений, як тривалий цикл, але оскільки наступний код не закінчується за короткий проміжок часу, швидше за все, повне 2 32 :
$start = r();
$i++ while $start != r();
print $i;
Perl 39/10 = 3,9
$s=$^T;sub r{~($s=$s*$s%4294969373)||r}
Примітка: якщо ви шукаєте PRNG Blum-Blum-Shub-esque, рішення Кіта Рандалла набагато краще, ніж будь-яке з них.
Як і моє оригінальне рішення нижче, це також реалізація Shub Blum Shub, з однією головною відмінністю. Я використовую модуль, трохи більший за 2 32 ( M = 50971 • 84263 ), і кожного разу, коли виникає значення, що воно не є дійсним 32-бітовим цілим числом (тобто більшим за 2 32 ), воно повертає наступне значення у обертання замість цього. По суті, ці значення викреслюються, залишаючи решту обертання непорушеним, що призводить до майже рівномірного розподілу.
Здається, це допомогло. Окрім того, що пройшов ті ж 9 тестів, що і раніше, він також переконливо проходить тест на мінімальну відстань. Зразок файлу журналу можна знайти тут .
Perl 33/9 ≈ 3,67 (недійсний?)
$s=$^T;sub r{$s=$s*$s%4294951589}
Примітка. Це рішення може вважатися недійсним, оскільки найвищі 0,00037% діапазону ніколи не будуть спостерігатися.
Швидке та брудне впровадження Blum Blum Shub . Я вимагаю таких результатів:
1. passed - Birthday Spacings
2. FAILED - Overlapping Permutations
3. passed - Ranks of 31x31 and 32x32 Matrices
4. passed - Ranks of 6x8 Matrices
5. FAILED - Monkey Tests on 20-bit Words
6. FAILED - Monkey Tests OPSO, OQSO, DNA
7. FAILED - Count the 1s in a Stream of Bytes
8. passed - Count the 1s for Specific Bytes
9. passed - Parking Lot Test
10. FAILED - Minimum Distance Test
11. passed - Random Spheres Test
12. FAILED - The Squeeze Test
13. passed - Overlapping Sums Test
14. passed - Runs Test
15. passed - The Craps Test
Зразок файлу журналу можна знайти тут , сміливо оскаржуйте будь-який результат. Файл для diehard можна створити наступним чином:
print pack('N', r()) for 1..4194304
а потім трубопровідний файл у файл. Мінімальна відстань виглядає так, що вона могла пройти, але якщо пропустити її кілька разів, це завжди дуже близько 1,0 , що вказує на збій.
Деталі
Взагалі, Blum Blum Shub - це жахливий PRNG, але його продуктивність можна покращити, вибравши хороший модуль. M Я вибрав це 7027 • 611207 . Обидва ці основні фактори, p і q , мають модульний залишок 3 (mod 4) і gcd (φ (p-1), φ (q-1)) = 2 , який є настільки низьким, наскільки це може бути.
Хоча це єдині критерії, перелічені на сторінці вікі, це здається недостатньо. Практично вся модуль, яку я спробував, провалила кожен тест. Але є жменька, яка пройде деякі тести, і те, що я вибрав, здається, надзвичайно хорошим, з будь-якої причини.
На завершення, тест 5 сам по собі здається досить хорошим показником того, наскільки хороший PRNG. Якщо він майже не пройде Тест 5, він ретельно вийде з ладу.
БОНУС: Perl 62/14 ≈ 4,43
$t=$^T;sub r{$t|=(($s=$s/2|$t%2<<31)^($t/=2))<<31for 1..37;$t}
Тільки для geekery, це 32-розрядна версія PRNG, яка використовується в оригінальному тетрісі для NES. Дивно, але він проходить 14 з 15 тестів!
1. passed - Birthday Spacings
2. passed - Overlapping Permutations
3. passed - Ranks of 31x31 and 32x32 Matrices
4. passed - Ranks for 6x8 Matrices
5. passed - Monkey Tests on 20-bit Words
6. passed - Monkey Tests OPSO, OQSO, DNA
7. FAILED - Count the 1s in a Stream of Bytes
8. passed - Count the 1s for Specific Bytes
9. passed - Parking Lot Test
10. passed - Minimum Distance Test
11. passed - Random Spheres Test
12. passed - The Squeeze Test
13. passed - Overlapping Sums Test
14. passed - Runs Test
15. passed - The Craps Test
Зразок файлу журналу можна тут .
Справді, 1..37
біт не є точною транскрипцією. У початковій версії розпорядок ентропії оновлюється 60 разів на секунду, а потім запитується через випадкові інтервали, багато в чому залежать від введення користувача. Для всіх, хто хотів би розібрати ПЗУ, розпочалася програма ентропії 0xAB47
.
Псевдокод стилю Python:
carry = entropy_1 & 1
entropy_1 >>= 1
entropy_2 = (entropy_2 >> 1) | (carry << 31)
carry = (entropy_1 & 1) ^ (entropy_2 & 1)
entropy_1 |= carry << 31