Perl 28/13 ≈ 2,15
sub r{$s^=~($s^=$s/7215)<<8}
journal ici
Perl 29/13 ≈ 2.23
sub r{$s^=~($s^=$s<<8)/60757}
journal ici
Il s’agit d’une variante du Xorshift , qui utilise une division en virgule flottante au lieu d’un décalage à droite. Ils ont tous deux réussi 13 des 15 tests, échouant seulement aux tests 6 et 7.
Je ne sais pas exactement combien de temps le cycle est, mais comme le code suivant ne se termine pas dans un court laps de temps, il est probable que le code 2 32 complet :
$start = r();
$i++ while $start != r();
print $i;
Perl 39/10 = 3,9
$s=$^T;sub r{~($s=$s*$s%4294969373)||r}
Remarque: si vous recherchez un PRNG Blum-Blum-Shub-esque, la solution de Keith Randall est bien meilleure que l’un ou l’autre.
Comme pour ma solution originale ci-dessous, il s'agit également d'une implémentation du Blum Blum Shub, avec une différence majeure. J'utilise un module légèrement supérieur à 2 32 ( M = 50971 • 84263 ), et chaque fois qu'une valeur est rencontrée qu'il ne s'agit pas d'un entier 32 bits valide (supérieur à 2 32 ), il renvoie la valeur suivante dans le champ. rotation à la place. En substance, ces valeurs sont élaguées, laissant le reste de la rotation non perturbé, ce qui permet une distribution presque uniforme.
Cela semble avoir aidé. En plus de réussir les mêmes 9 tests qu'auparavant, il passe également le test Distance minimale de manière convaincante. Vous trouverez un exemple de fichier journal ici .
Perl 33/9 ≈ 3,67 (invalide?)
$s=$^T;sub r{$s=$s*$s%4294951589}
Remarque: cette solution peut être considérée comme non valide car les 0,00037% supérieurs de la plage ne seront jamais observés.
Une mise en œuvre rapide et sale du Blum Blum Shub . Je réclame les résultats suivants:
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
Vous trouverez un exemple de fichier journal ici . N'hésitez pas à contester les résultats. Le fichier pour diehard peut être généré de la manière suivante:
print pack('N', r()) for 1..4194304
puis canaliser la sortie dans un fichier. La Distance minimale semble avoir été dépassée, mais si vous l'exécutez plusieurs fois, elle est toujours très proche de 1,0 , ce qui indique un échec.
Détails
En général, le Blum Blum Shub est un PRNG terrible, mais ses performances peuvent être améliorées en choisissant un bon module. Le M que j'ai choisi est 7027 • 611207 . Les deux facteurs premiers, p et q , ont un résidu modulaire 3 (mod 4) et gcd ((p-1), φ (q-1)) = 2 , ce qui est aussi faible que possible.
Bien que ce soient les seuls critères listés sur la page du wiki, cela ne semble pas être suffisant. Presque tout le modulo que j'ai essayé a échoué à tous les tests. Mais il y en a une poignée qui va passer certains des tests, et celui que j'ai choisi semble être exceptionnellement bon, peu importe la raison.
En conclusion, le test 5 semble à lui seul être un assez bon indicateur de la qualité du PRNG. S'il ne passe presque pas le test 5, les autres échoueront de manière spectaculaire.
BONUS: Perl 62/14 4.43
$t=$^T;sub r{$t|=(($s=$s/2|$t%2<<31)^($t/=2))<<31for 1..37;$t}
Juste pour geekery, il s'agit d'une version 32 bits du PRNG utilisée dans le Tetris d'origine pour NES. Étonnamment, il passe 14 des 15 tests!
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
Exemple de fichier journal peut avant ici .
Certes, le 1..37
bit n'est pas une transcription exacte. Dans la version originale, la routine d'entropie est mise à jour 60 fois par seconde, puis interrogée à intervalles aléatoires, en grande partie en fonction des entrées de l'utilisateur. Pour ceux qui souhaitent démonter la ROM, la routine d'entropie commence à 0xAB47
.
Pseudo-code de style 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