Math.random () ve Random.nextInt (int) karşılaştırması


135

Tam sayı arasındaki fark nedir Math.random() * nve tam sayı Random.nextInt(n)nerede n?


Matematiği bilmiyorum, ama eğer kullanırsanız FindBugs'ın şikayet ettiğini biliyorumMath.random()
finnw

3
Random'ın statik bir yöntemi olmadığını unutmayın, bu yüzden şunu kullanın: (new Random ()). NextInt (n)). Math'ın benzer bir tamsayı üretmesi için: Math.floor ((Math.random () * n) +1);
Dimitri Dewaele

Yanıtlar:


169

Gili'nin bağlı olduğu Güneş forumları gönderisinden " neden hem daha etkili hem de daha az önyargılı " olduğunu gösteren ayrıntılı açıklama :Random.nextInt(n)Math.random() * n

Math.random () dahili olarak Random.nextDouble () kullanır.

Random.nextDouble (), mantisinde yaklaşık olarak eşit olarak dağılmış bitleri olan bir çift oluşturmak için Random.next () öğesini iki kez kullanır, bu nedenle 0 ila 1- (2 ^ -53) aralığında eşit olarak dağıtılır.

Random.nextInt (n), ortalama olarak iki kereden daha az Random.next () kullanır - bir kez kullanır ve elde edilen değer MAX_INT altındaki n'nin en yüksek katının üzerindeyse tekrar dener, aksi takdirde n modulo değerini döndürür (bu MAX_INT öğesinin altındaki en yüksek katının üstündeki değerleri dağıtımı azaltarak önler), bu nedenle 0 ile n-1 arasında eşit olarak dağıtılmış bir değer döndürür.

6 ile ölçeklendirmeden önce, Math.random () çıktısı, tekdüze bir dağılımdan alınan 2 ^ 53 olası değerden biridir.

6'ya ölçeklendirme olası değerlerin sayısını değiştirmez ve bir int'e döküm yapmak, bu değerleri altı 'kovadan (0, 1, 2, 3, 4, 5) birine zorlar; her bir kova, 1501199875790165 veya 1501199875790166 olası değerlerin (6 olduğu için 2 ^ 53 değildir). Bu, yeterli sayıda zar rulosu (veya yeterince çok sayıda kenarı olan bir kalıp) için kalıbın daha büyük kovalara doğru eğimli olduğunu göstereceği anlamına gelir.

Bu etkinin ortaya çıkması için zarları çok uzun süre bekleyeceksiniz.

Math.random () ayrıca işlemin yaklaşık iki katı gerektirir ve senkronizasyona tabidir.


3
Random.nextInt ve nextDouble de senkronizasyona tabidir.
adrianos

Bu bağlamda, "daha az önyargılı" ne demek lütfen?
ęXocę 웃 Пepeúpa ツ

2
@ ΦXocę 웃 Пepeúpa simply Bu, belirli sayıların çizilmesinin diğerlerinden daha muhtemel olduğu anlamına gelir. İçinde olduğu gibi diğerleri üzerinde bazı sayılar seçmek için önyargılı (bu nedenle tamamen rastgele değil veya yeterince büyük örnek boyutu üniforma verildi)
ford kaymakam

1
Bu iş parçacığının son yorumunun şunları bildirdiğine dikkat edin: "Açıklanan sapma 2 ^ 53'te bir bölümdür, ancak kullanılan PRNG'nin maksimum döngü uzunluğu yalnızca 2 ^ 48'dir. Yani uygulamada göreceğiniz veriler önyargının değil, altta yatan PRNG'nin dağılımı. " Bu iki yöntem eşdeğer olduğu gerçeğine işaret eder
dijital yanılsama

1
@ ΦXocę 웃 Пepeúpa ツBir zar küpü 6ile değiştirin 5: "5-biased" olacaktır. Zarda bir şeylerin yanlış olduğunu fark etmeden önce zarları birkaç kez atabilirsiniz. Rastgele bir jeneratörde bir şeyin yanlış olduğunu fark etmeden önce son derece sofistike bir inceleme yapmak zorundasınız.
Dávid Horváth

27

bir başka önemli nokta, aynı tohum ile iki Rastgele nesne oluşturabildiğiniz için Random.nextInt (n) tekrarlanabilir olmasıdır . Math.random () ile bu mümkün değildir.



0

Bu örneğe göre Random.nextInt(n)Math.random () * n'den daha az öngörülebilir çıktıya sahiptir. [Sıralanmamış dizi sıralanmamış bir diziden daha hızlı] göre [1] Ben Random.nextInt (n) tahmin etmek zor olduğunu söyleyebiliriz .

usingRandomClass: süre: 328 milisaniye.

usingMathsRandom: süre: 187 milisaniye.

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));

    }

}

1
İkinci döngüde, vakaların% 50'sinden fazlası için geçerli olan = = 50'yi kontrol edersiniz. Bu, eğer if ifadesinin çoğu zaman doğru olmasına neden olur, bu da onu daha öngörülebilir kılar. Bu nedenle sonuçlarınız cevabınızın lehine önyargılıdır
Neuron

bu yazım hatasıdır ... ikinci örnekte 128 yapın aynı sonucu elde edersiniz.
jatin Goyal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.