Tahun Baru Cina akan segera hadir. Amplop merah WeChat sangat populer selama Tahun Baru Cina. Baru -baru ini, sebuah proyek juga ingin meraih amplop merah, jadi saya menulis algoritma generasi amplop merah.
Persyaratan untuk algoritma generasi amplop merah
Pra-buat semua amplop merah atau menghasilkan satu amplop merah secara acak jika satu permintaan
Sederhananya, ini adalah proses menguraikan integer besar M (langsung dalam unit "membagi menjadi" unit, seperti 1 yuan, yaitu, 100) menjadi n bilangan bulat kecil. Kisaran bilangan bulat kecil adalah [Min, Max].
Gagasan paling sederhana adalah untuk menjamin garis bawah terlebih dahulu, setiap amplop merah kecil memiliki min, dan kemudian setiap permintaan secara acak menghasilkan bilangan bulat mulai dari 0 hingga (maks-min), dan kemudian tambahkan min ke uang amplop merah.
Meskipun algoritma ini sederhana, ia memiliki satu kerugian: amplop merah yang dihasilkan pada akhirnya mungkin semua uang min. Dengan kata lain, amplop merah terakhir mungkin 0,01 yuan.
Cara lain adalah dengan membuat pra-membuat semua amplop merah, sehingga lebih mudah dikendalikan. Saya memilih untuk membuat pra-membuat semua amplop merah.
Algoritma generasi amplop merah yang ideal
Hasil generasi amplop merah yang ideal adalah bahwa ada lebih banyak amplop merah di dekat nilai rata -rata, dan ada relatif sedikit amplop merah besar dan amplop merah kecil.
Seperti yang dapat Anda bayangkan, distribusi jumlah paket merah yang dihasilkan sedikit seperti distribusi normal.
Jadi bagaimana mencapai persyaratan lebih banyak nilai di dekat garis rata -rata?
Ini untuk menemukan algoritma yang dapat meningkatkan probabilitas di sekitar rata -rata. Kemudian gunakan metode "ekspansi" dan "kontraksi" untuk mencapai efek ini.
Jika Anda pertama kali kuadrat, maka hasilkan angka acak dalam kisaran kuadrat, dan kemudian persegi, maka probabilitasnya tidak akan lagi rata -rata.
Algoritma spesifik:
kelas publik hongbaoalgorithm {static random acak = acak baru (); static {randomEseed (SystemCurrentTimeMillis ()); } public static void main (string [] args) {long max = 200; Min long = 1; long [] hasil = hongbaoalgorithmgenerate (100_0000, 10_000, maks, min); Total panjang = 0; untuk (int i = 0; i <resultLength; i ++) {// systemoutprintln ("result [" + i + "]:" + hasil [i]); // SystemeMoutPrintln (hasil [i]); Total += hasil [i]; } // Periksa apakah jumlah total paket merah yang dihasilkan adalah yang benar SystemeMoutPrintln ("Total:" + Total); // Hitung jumlah paket merah untuk setiap uang dan periksa apakah itu dekat dengan jumlah int distribusi normal [] = int baru [(int) max + 1]; untuk (int i = 0; i <resultLength; i ++) {count [(int) hasil [i]]+= 1; } untuk (int i = 0; i <countlength; i ++) {SystemeMoutPrintln ("" + i + "" + count [i]); }} /*** Menghasilkan angka acak antara min dan max, tetapi probabilitasnya tidak rata -rata, dan probabilitas dari min ke arah maksimum secara bertahap meningkat. * Kotak pertama, kemudian menghasilkan nomor acak dalam kisaran nilai kuadrat, dan kemudian persegi, yang menghasilkan efek "ekspansi" dan "penyusutan". * * @param min * @param max * @return */ static long xrandom (long min, long max) {return sqrt (nextLong (sqr (maks - min)))); } /** * * @param total * Total red envelope amount* @param count * Number of red envelopes* @param max * Maximum amount of each small red envelope* @param min * Minimum amount of each small red envelope* @return Array of values of each small red envelope generated*/ public static long[] generate(long total, int count, long max, long min) { long[] result = new long[count]; rata -rata panjang = total / hitung; long a = rata -rata - min; long b = max - min; // // Probabilitas angka acak seperti itu sebenarnya telah berubah, dan kemungkinan menghasilkan jumlah besar lebih kecil dari probabilitas menghasilkan angka desimal. // Ini mencapai bahwa sebagian besar amplop merah memiliki nilai di sekitar rata -rata. Ada lebih sedikit amplop merah besar dan amplop merah kecil. long range1 = sqr (rata -rata - min); long range2 = sqr (maks - rata -rata); untuk (int i = 0; i <resultLength; i ++) {// Karena jumlah amplop merah kecil biasanya lebih tinggi dari jumlah amplop merah besar, karena probabilitas di sini perlu diubah. // Ketika nomor acak> nilai rata -rata, amplop merah kecil dihasilkan // Ketika angka acak <nilai rata -rata, amplop merah besar dihasilkan jika (selanjutnya (min, max)> rata -rata) {// mengurangi uang pada baris rata -rata // temp long = min + sqrt (nextLong (range1))); Temp panjang = min + xrandom (min, rata -rata); Hasil [i] = temp; Total -= temp; } else {// tambahkan uang pada baris rata -rata // temp = max - sqrt (nextLong (range2)); Temp panjang = maks - xrandom (rata -rata, maks); Hasil [i] = temp; Total -= temp; }} // Jika masih ada uang yang tersisa, coba tambahkan ke dalam amplop merah kecil. Jika tidak dapat ditambahkan, coba yang berikutnya. while (total> 0) {for (int i = 0; i <resultLength; i ++) {if (total> 0 && result [i] <max) {hasil [i] ++; total--; }}} // Jika uangnya negatif, Anda harus menarik kembali dari amplop merah kecil yang dihasilkan sementara (total <0) {untuk (int i = 0; i <resultLength; i ++) {if (total <0 && hasil [i]> min) {hasil [i]-; Total ++; }}} hasil pengembalian; } static long sqrt (long n) {// ditingkatkan ke tabel pencarian? return (long) mathsqrt (n); } static long sqr (long n) {// Apakah tabel pencarian cepat, atau apakah secara langsung dihitung dengan cepat? kembali n * n; } static long nextLong (long n) {return randomNextInt ((int) n); } static long nextLong (long min, long max) {return randomNextInt ((int) (maks - min + 1)) + min; }}Setelah menghitung hasil yang dihasilkan, mereka cukup sesuai dengan persyaratan.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.