Biarkan saya minta maaf sebelumnya, karena ini agak sulit untuk dipahami ...
Pertama-tama, Anda sudah tahu bahwa java.util.Random
itu tidak sepenuhnya acak sama sekali. Ini menghasilkan urutan dengan cara yang dapat diprediksi dengan sempurna dari seed. Anda sepenuhnya benar bahwa, karena benih hanya panjang 64 bit, hanya dapat menghasilkan 2 ^ 64 urutan yang berbeda. Jika Anda entah bagaimana menghasilkan 64 bit acak nyata dan menggunakannya untuk memilih sebuah seed, Anda tidak dapat menggunakan seed itu untuk secara acak memilih di antara semua 52! kemungkinan urutan dengan probabilitas yang sama.
Namun, fakta ini tidak ada konsekuensi selama Anda tidak benar-benar akan menghasilkan lebih dari 2 ^ 64 sekuens, selama tidak ada yang 'istimewa' atau 'terasa istimewa' tentang sekuens 2 ^ 64 yang dapat dihasilkan dihasilkannya .
Katakanlah Anda memiliki PRNG yang jauh lebih baik yang menggunakan biji 1000-bit. Bayangkan Anda memiliki dua cara untuk menginisialisasi - satu cara akan menginisialisasi menggunakan seluruh benih, dan satu cara akan memotong benih menjadi 64 bit sebelum menginisialisasi itu.
Jika Anda tidak tahu inisialisasi mana yang mana, bisakah Anda menulis segala jenis tes untuk membedakannya? Kecuali jika Anda (tidak) cukup beruntung untuk akhirnya menginisialisasi yang buruk dengan yang sama 64 bit yang dua kali, maka jawabannya adalah tidak. Anda tidak dapat membedakan antara kedua inisialisasi tanpa sedikit pengetahuan rinci tentang beberapa kelemahan dalam implementasi PRNG tertentu.
Atau, bayangkan bahwa Random
kelas memiliki array 2 ^ 64 urutan yang dipilih sepenuhnya dan acak pada suatu waktu di masa lalu, dan bahwa benih itu hanya indeks ke dalam array ini.
Jadi fakta yang Random
hanya menggunakan 64 bit untuk bijinya sebenarnya tidak selalu menjadi masalah secara statistik, selama tidak ada peluang signifikan bahwa Anda akan menggunakan seed yang sama dua kali.
Tentu saja, untuk keperluan kriptografi , seed 64 bit tidak cukup, karena mendapatkan sistem untuk menggunakan seed yang sama dua kali layak secara komputasi.
EDIT:
Saya harus menambahkan bahwa, meskipun semua hal di atas benar, bahwa implementasi sebenarnya java.util.Random
tidak mengagumkan. Jika Anda menulis permainan kartu, mungkin menggunakan MessageDigest
API untuk menghasilkan hash SHA-256 "MyGameName"+System.currentTimeMillis()
, dan menggunakan bit-bit itu untuk mengocok deck. Dengan argumen di atas, selama pengguna Anda tidak benar-benar berjudi, Anda tidak perlu khawatir itu akan currentTimeMillis
kembali lama. Jika pengguna Anda benar - benar berjudi, maka gunakan SecureRandom
tanpa benih.
Random
tidak pernah angka acak nyata . Ini adalah PRNG, di mana P berarti "semu". Untuk bilangan acak nyata , Anda memerlukan sumber keacakan (seperti random.org).