Mulai dari kutipan Skeet ini:
Ini bukan cara pengocokan yang saya sukai, sebagian besar dengan alasan itu adalah O (n log n) tanpa alasan yang baik ketika mudah untuk menerapkan pengocokan O (n). Kode dalam pertanyaan "berfungsi" pada dasarnya memberikan nomor acak ( semoga unik! ) Untuk setiap elemen, lalu memesan elemen sesuai dengan nomor itu.
Saya akan menjelaskan sedikit alasan untuk semoga unik!
Sekarang, dari Enumerable.OrderBy :
Metode ini melakukan semacam stabil; yaitu, jika kunci dua elemen sama, urutan elemen dipertahankan
Ini sangat penting! Apa yang terjadi jika dua elemen "menerima" nomor acak yang sama? Itu terjadi bahwa mereka tetap dalam urutan yang sama mereka berada di array. Sekarang, bagaimana kemungkinan ini terjadi? Sulit untuk menghitung dengan tepat, tetapi ada Masalah Ulang Tahun yang justru merupakan masalah ini.
Sekarang, benarkah? Apakah itu benar
Seperti biasa, ketika ragu, tulis beberapa baris program: http://pastebin.com/5CDnUxPG
Blok kecil kode ini mengocok array 3 elemen beberapa kali menggunakan algoritma Fisher-Yates yang dilakukan mundur, algoritma Fisher-Yates dilakukan ke depan (pada halaman wiki ada dua algoritma pseudo-code ... Mereka menghasilkan setara hasil, tetapi satu dilakukan dari elemen pertama ke elemen terakhir, sedangkan yang lain dilakukan dari elemen terakhir ke elemen pertama), algoritma salah naif dari http://blog.codinghorror.com/the-danger-of-naivete/ dan menggunakan .OrderBy(x => r.Next())
dan .OrderBy(x => r.Next(someValue))
.
Sekarang, Random.Next adalah
Bilangan bulat bertanda 32-bit yang lebih besar dari atau sama dengan 0 dan kurang dari MaxValue.
jadi itu setara dengan
OrderBy(x => r.Next(int.MaxValue))
Untuk menguji apakah masalah ini ada, kita dapat memperbesar array (sesuatu yang sangat lambat) atau cukup mengurangi nilai maksimum dari generator angka acak ( int.MaxValue
bukan nomor "khusus" ... Ini hanyalah angka yang sangat besar). Pada akhirnya, jika algoritma tidak bias oleh stableness dariOrderBy
, maka rentang nilai apa pun harus memberikan hasil yang sama.
Program kemudian menguji beberapa nilai, dalam kisaran 1 ... 4096. Melihat hasilnya, cukup jelas bahwa untuk nilai rendah (<128), algoritmenya sangat bias (4-8%). Dengan 3 nilai yang Anda butuhkan setidaknya r.Next(1024)
. Jika Anda membuat array lebih besar (4 atau 5), maka itu pun r.Next(1024)
tidak cukup. Saya bukan ahli dalam pengocokan dan matematika, tapi saya pikir untuk setiap bit ekstra panjang array, Anda memerlukan 2 bit ekstra dari nilai maksimum (karena paradoks ulang tahun terhubung ke sqrt (numvalues)), jadi bahwa jika nilai maksimum adalah 2 ^ 31, saya akan mengatakan bahwa Anda harus dapat mengurutkan array hingga 2 ^ 12/2 ^ 13 bit (4096-8192 elemen)