Perl 28/13 ≈ 2.15
sub r{$s^=~($s^=$s/7215)<<8}
file log di sini
Perl 29/13 ≈ 2.23
sub r{$s^=~($s^=$s<<8)/60757}
file log di sini
Ini adalah sesuatu variasi pada Xorshift , menggunakan pembagian floating point alih-alih shift yang tepat. Keduanya lulus 13 dari 15 tes, hanya gagal tes 6 dan 7.
Saya tidak yakin berapa lama siklusnya, tetapi karena kode berikut ini tidak berakhir dalam waktu singkat, kemungkinan penuh 2 32 :
$start = r();
$i++ while $start != r();
print $i;
Perl 39/10 = 3,9
$s=$^T;sub r{~($s=$s*$s%4294969373)||r}
Catatan: jika Anda mencari PRNG Blum-Blum-Shub-esque, solusi Keith Randall jauh lebih baik daripada keduanya.
Seperti dengan solusi asli saya di bawah ini, ini juga merupakan implementasi dari Blum Blum Shub, dengan satu perbedaan utama. Saya menggunakan modulus sedikit lebih besar dari 2 32 ( M = 50971 • 84263 ), dan setiap kali nilai ditemukan bahwa itu bukan bilangan bulat 32-bit yang valid (yaitu, lebih besar dari 2 32 ), ia mengembalikan nilai berikutnya dalam rotasi sebagai gantinya. Pada dasarnya, nilai-nilai ini dipangkas, meninggalkan sisa rotasi tidak terganggu, menghasilkan distribusi yang hampir seragam.
Tampaknya telah membantu. Selain lulus 9 tes yang sama seperti sebelumnya, sekarang dengan meyakinkan melewati tes Jarak Minimum. File log sampel dapat ditemukan di sini .
Perl 33/9 ≈ 3.67 (Tidak valid?)
$s=$^T;sub r{$s=$s*$s%4294951589}
Catatan: solusi ini mungkin dianggap tidak valid, karena 0,00037% teratas dari rentang tidak akan pernah diamati.
Implementasi Blum Blum Shub yang cepat dan kotor . Saya mengklaim hasil berikut:
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
File log sampel dapat ditemukan di sini , jangan ragu untuk menyengketakan hasil apa pun. File untuk diehard dapat dibuat dengan cara berikut:
print pack('N', r()) for 1..4194304
dan kemudian menyalurkan output ke file. Jarak Minimum sepertinya sudah terlewati, tetapi jika Anda menjalankannya berkali-kali selalu sangat dekat dengan 1,0 , yang mengindikasikan kegagalan.
Detail
Secara umum, Blum Blum Shub adalah PRNG yang mengerikan, tetapi kinerjanya dapat ditingkatkan dengan memilih modulus yang baik. The M Aku telah memilih adalah 7027 • 611.207 . Kedua faktor utama ini, p dan q , memiliki residu modular 3 (mod 4) , dan gcd (φ (p-1), φ (q-1)) = 2 , yang serendah mungkin.
Meskipun ini adalah satu-satunya kriteria yang tercantum pada halaman wiki, sepertinya tidak cukup. Hampir semua modulo yang saya coba gagal setiap tes. Tetapi ada beberapa yang akan lulus beberapa tes, dan yang saya pilih tampaknya sangat bagus, untuk alasan apa pun.
Sebagai catatan terakhir, Tes 5 sendiri tampaknya menjadi indikator yang cukup baik tentang seberapa baik PRNG. Jika hampir tidak lulus Tes 5, itu akan gagal sisanya secara spektakuler.
BONUS: Perl 62/14 ≈ 4.43
$t=$^T;sub r{$t|=(($s=$s/2|$t%2<<31)^($t/=2))<<31for 1..37;$t}
Hanya untuk geekery, ini adalah versi 32-bit dari PRNG yang digunakan dalam Tetris asli untuk NES. Hebatnya, ini lulus 14 dari 15 tes!
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
Sampel file log bisa sebelum di sini .
Memang, 1..37
bit itu bukan transkripsi yang tepat. Dalam versi asli, rutin entropi diperbarui 60 kali per detik, dan kemudian ditanyai secara acak, sebagian besar tergantung pada input pengguna. Bagi siapa pun yang ingin membongkar ROM, rutinitas entropi dimulai pada 0xAB47
.
Kode semu gaya-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