Perl 28/13 ≈ 2.15
sub r{$s^=~($s^=$s/7215)<<8}
archivo de registro aquí
Perl 29/13 ≈ 2.23
sub r{$s^=~($s^=$s<<8)/60757}
archivo de registro aquí
Estos son una especie de variación en un Xorshift , utilizando la división de punto flotante en lugar de un desplazamiento a la derecha. Ambos pasan 13 de 15 pruebas, fallando solo las pruebas 6 y 7.
No estoy exactamente seguro de cuánto dura el ciclo, pero debido a que el siguiente código no termina en un período corto de tiempo, es probable que sea el 2 32 completo :
$start = r();
$i++ while $start != r();
print $i;
Perl 39/10 = 3.9
$s=$^T;sub r{~($s=$s*$s%4294969373)||r}
Nota: si está buscando un PRNG Blum-Blum-Shub-esque, la solución de Keith Randall es mucho mejor que cualquiera de estos.
Al igual que con mi solución original a continuación, esta también es una implementación de Blum Blum Shub, con una gran diferencia. Utilizo un módulo ligeramente mayor que 2 32 ( M = 50971 • 84263 ), y cada vez que se encuentra un valor que no es un entero de 32 bits válido (es decir, mayor que 2 32 ), devuelve el siguiente valor en el rotación en su lugar. En esencia, estos valores se eliminan, dejando el resto de la rotación sin perturbaciones, lo que resulta en una distribución casi uniforme.
Parece haber ayudado. Además de pasar las mismas 9 pruebas que antes, ahora también pasa convincentemente la prueba de Distancia mínima. Puede encontrar un archivo de registro de muestra aquí .
Perl 33/9 ≈ 3.67 (¿No válido?)
$s=$^T;sub r{$s=$s*$s%4294951589}
Nota: esta solución puede considerarse inválida, ya que nunca se observará el 0,00037% superior del rango.
Una implementación rápida y sucia del Blum Blum Shub . Reclamo los siguientes resultados:
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
Puede encontrar un archivo de registro de muestra aquí , no dude en disputar cualquiera de los resultados. El archivo para diehard se puede generar de la siguiente manera:
print pack('N', r()) for 1..4194304
y luego canalizando la salida en un archivo. Parece que la distancia mínima puede haber pasado, pero si la ejecuta varias veces, siempre está muy cerca de 1.0 , lo que indica un error.
Detalles
En general, el Blum Blum Shub es un PRNG terrible, pero su rendimiento se puede mejorar eligiendo un buen módulo. La M que he elegido es 7027 • 611207 . Ambos factores primos, p y q , tienen un residuo modular 3 (mod 4) y mcd (φ (p-1), φ (q-1)) = 2 , que es lo más bajo posible.
Aunque estos son los únicos criterios enumerados en la página wiki, no parece ser suficiente. Casi todo el módulo que probé falló en cada prueba. Pero hay un puñado que pasará algunas de las pruebas, y la que he elegido parece ser excepcionalmente buena, por cualquier razón.
Como nota final, la Prueba 5 por sí sola parece ser un indicador bastante bueno de lo bueno que es el PRNG. Si casi no pasa la Prueba 5, fallará al resto espectacularmente.
BONIFICACIÓN: Perl 62/14 ≈ 4.43
$t=$^T;sub r{$t|=(($s=$s/2|$t%2<<31)^($t/=2))<<31for 1..37;$t}
Solo por geekery, esta es una versión de 32 bits del PRNG utilizada en el Tetris original para NES. Sorprendentemente, ¡pasa 14 de las 15 pruebas!
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
Ejemplo de archivo de registro puede antes aquí .
Es cierto que el 1..37
bit no es una transcripción exacta. En la versión original, la rutina de entropía se actualiza 60 veces por segundo y luego se consulta a intervalos aleatorios, dependiendo en gran medida de la entrada del usuario. Para cualquiera que se preocupe por desmontar la ROM, la rutina de entropía comienza en 0xAB47
.
Seudocódigo de estilo 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