Saya tidak tahu matematika, tetapi saya tahu bahwa FindBugs mengeluh jika Anda menggunakanMath.random()
finnw
3
Ingat bahwa Random tidak memiliki metode statis, jadi gunakan: (new Random ()). NextInt (n)). Untuk Matematika untuk menghasilkan penggunaan integer yang serupa: Math.floor ((Math.random () * n) +1);
Dimitri Dewaele
Jawaban:
172
Berikut adalah penjelasan rinci tentang mengapa " Random.nextInt(n)lebih efisien dan tidak terlalu bias Math.random() * n" dari posting forum Sun yang ditautkan ke Gili:
Math.random () menggunakan Random.nextDouble () secara internal.
Random.nextDouble () menggunakan Random.next () dua kali untuk menghasilkan double yang kira-kira memiliki bit terdistribusi seragam dalam mantisanya, sehingga didistribusikan secara seragam dalam rentang 0 hingga 1- (2 ^ -53).
Random.nextInt (n) menggunakan Random.next () rata-rata kurang dari dua kali- menggunakannya sekali, dan jika nilai yang diperoleh di atas kelipatan tertinggi n di bawah MAX_INT mencoba lagi, jika tidak mengembalikan nilai modulo n (ini mencegah nilai di atas kelipatan n tertinggi di bawah MAX_INT yang mengubah distribusi), sehingga mengembalikan nilai yang terdistribusi secara seragam dalam rentang 0 hingga n-1.
Sebelum penskalaan 6, output Math.random () adalah salah satu dari 2 ^ 53 kemungkinan nilai yang diambil dari distribusi seragam.
Penskalaan 6 tidak mengubah jumlah nilai yang mungkin, dan mentransmisikan ke int kemudian memaksa nilai-nilai ini ke dalam salah satu dari enam 'keranjang' (0, 1, 2, 3, 4, 5), setiap keranjang sesuai dengan rentang yang mencakup baik 1501199875790165 atau 1501199875790166 dari nilai yang mungkin (karena 6 bukanlah pembagi 2 ^ 53). Ini berarti bahwa untuk jumlah lemparan dadu yang cukup (atau dadu dengan jumlah sisi yang cukup banyak), dadu akan menunjukkan dirinya bias ke arah ember yang lebih besar.
Anda akan menunggu waktu yang sangat lama untuk melempar dadu hingga efek ini muncul.
Math.random () juga membutuhkan sekitar dua kali pemrosesan dan dapat disinkronkan.
Random.nextInt dan nextDouble juga tunduk pada sinkronisasi.
adrianos
Dalam konteks ini, apa artinya "kurang bias"?
ΦXocę 웃 Пepeúpa ツ
2
@ ΦXocę 웃 Пepeúpa ツ Ini berarti bahwa nomor tertentu lebih mungkin untuk ditarik daripada yang lain. Seperti di dalamnya bias untuk memilih beberapa nomor di atas yang lain (karenanya tidak sepenuhnya acak atau diberi seragam ukuran sampel yang cukup besar)
ford prefek
1
Perhatikan bahwa komentar terakhir untuk utas itu melaporkan: "Bias yang dijelaskan adalah satu bagian dalam 2 ^ 53, tetapi panjang siklus maksimum PRNG yang digunakan hanya 2 ^ 48. Jadi yang akan Anda lihat di aplikasi adalah datanya distribusi PRNG yang mendasarinya, bukan biasnya. " Ini akan menunjukkan fakta bahwa kedua metode itu setara
ilusi digital
2
@ ΦXocę 웃 Пepeúpa ツ Ganti 6dengan 5pada kubus dadu: itu akan menjadi "5-bias". Anda dapat melempar dadu beberapa kali sebelum Anda menyadari ada sesuatu yang salah dengan dadu tersebut. Anda dipaksa untuk melakukan pemeriksaan menyeluruh yang sangat canggih sebelum Anda melihat ada yang salah dengan generator acak.
Dávid Horváth
27
Poin penting lainnya adalah Random.nextInt (n) dapat diulang karena Anda dapat membuat dua objek Random dengan seed yang sama . Ini tidak mungkin dilakukan dengan Math.random ().
Saya akan merekomendasikan untuk benar-benar mengutip beberapa postingannya dan meringkas sedikit di sini. Tautan tersebut harus melengkapi jawaban Anda.
jjnguy
0
Menurut contoh ini Random.nextInt(n)memiliki keluaran yang kurang dapat diprediksi daripada Math.random () * n. Menurut [array yang diurutkan lebih cepat daripada array yang tidak diurutkan] [1] Saya rasa kita dapat mengatakan Random.nextInt (n) sulit untuk diprediksi .
usingRandomClass: waktu: 328 mil detik.
usingMathsRandom: waktu: 187 mil detik.
package javaFuction;
import java.util.Random;
publicclassRandomFuction{
staticint array[] = newint[9999];
staticlong sum = 0;
publicstaticvoidusingMathsRandom(){
for (int i = 0; i < 9999; i++) {
array[i] = (int) (Math.random() * 256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
publicstaticvoidusingRandomClass(){
Random random = new Random();
for (int i = 0; i < 9999; i++) {
array[i] = random.nextInt(256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
publicstaticvoidmain(String[] args){
long start = System.currentTimeMillis();
usingRandomClass();
long end = System.currentTimeMillis();
System.out.println("usingRandomClass " + (end - start));
start = System.currentTimeMillis();
usingMathsRandom();
end = System.currentTimeMillis();
System.out.println("usingMathsRandom " + (end - start));
}
}
Di loop kedua Anda memeriksa> = 50, yang benar di lebih dari 50% kasus. Itu akan menyebabkan pernyataan if ini menjadi benar sebagian besar waktu, yang membuatnya lebih dapat diprediksi. Oleh karena itu hasil Anda bias mendukung jawaban Anda
Neuron
itu adalah kesalahan ketik ... buat 128 di contoh kedua Anda akan mendapatkan hasil yang sama.
Math.random()
Jawaban:
Berikut adalah penjelasan rinci tentang mengapa "
Random.nextInt(n)
lebih efisien dan tidak terlalu biasMath.random() * n
" dari posting forum Sun yang ditautkan ke Gili:sumber
6
dengan5
pada kubus dadu: itu akan menjadi "5-bias". Anda dapat melempar dadu beberapa kali sebelum Anda menyadari ada sesuatu yang salah dengan dadu tersebut. Anda dipaksa untuk melakukan pemeriksaan menyeluruh yang sangat canggih sebelum Anda melihat ada yang salah dengan generator acak.Poin penting lainnya adalah Random.nextInt (n) dapat diulang karena Anda dapat membuat dua objek Random dengan seed yang sama . Ini tidak mungkin dilakukan dengan Math.random ().
sumber
Menurut https://forums.oracle.com/forums/thread.jspa?messageID=6594485龵
Random.nextInt(n)
lebih efisien dan tidak terlalu bias dibandingkanMath.random() * n
sumber
Menurut contoh ini
Random.nextInt(n)
memiliki keluaran yang kurang dapat diprediksi daripada Math.random () * n. Menurut [array yang diurutkan lebih cepat daripada array yang tidak diurutkan] [1] Saya rasa kita dapat mengatakan Random.nextInt (n) sulit untuk diprediksi .usingRandomClass: waktu: 328 mil detik.
usingMathsRandom: waktu: 187 mil detik.
package javaFuction; import java.util.Random; public class RandomFuction { static int array[] = new int[9999]; static long sum = 0; public static void usingMathsRandom() { for (int i = 0; i < 9999; i++) { array[i] = (int) (Math.random() * 256); } for (int i = 0; i < 9999; i++) { for (int j = 0; j < 9999; j++) { if (array[j] >= 128) { sum += array[j]; } } } } public static void usingRandomClass() { Random random = new Random(); for (int i = 0; i < 9999; i++) { array[i] = random.nextInt(256); } for (int i = 0; i < 9999; i++) { for (int j = 0; j < 9999; j++) { if (array[j] >= 128) { sum += array[j]; } } } } public static void main(String[] args) { long start = System.currentTimeMillis(); usingRandomClass(); long end = System.currentTimeMillis(); System.out.println("usingRandomClass " + (end - start)); start = System.currentTimeMillis(); usingMathsRandom(); end = System.currentTimeMillis(); System.out.println("usingMathsRandom " + (end - start)); } }
sumber