SORU
24 Ocak 2013, PERŞEMBE


Bu "yeterli" rasgele algoritması; neden değil't eğer kullanılan'ler daha hızlı?

Bir sınıf QuickRandom denilen yaptım ve işini hızlı bir şekilde rastgele sayılar üretmektir. Çok basit: eski değer,* *8, Bir ile çarpma ve ondalık kısmı.

Burada bütünüyle QuickRandom Dersim:

public class QuickRandom {
    private double prevNum;
    private double magicNumber;

    public QuickRandom(double seed1, double seed2) {
        if (seed1 >= 1 || seed1 < 0) throw new IllegalArgumentException("Seed 1 must be >= 0 and < 1, not "   seed1);
        prevNum = seed1;
        if (seed2 <= 1 || seed2 > 10) throw new IllegalArgumentException("Seed 2 must be > 1 and <= 10, not "   seed2);
        magicNumber = seed2;
    }

    public QuickRandom() {
        this(Math.random(), Math.random() * 10);
    }

    public double random() {
        return prevNum = (prevNum*magicNumber)%1;
    }

}

Ve burada bunu test etmek için yazdığım bir kod

public static void main(String[] args) {
        QuickRandom qr = new QuickRandom();

        /*for (int i = 0; i < 20; i   ) {
            System.out.println(qr.random());
        }*/

        //Warm up
        for (int i = 0; i < 10000000; i   ) {
            Math.random();
            qr.random();
            System.nanoTime();
        }

        long oldTime;

        oldTime = System.nanoTime();
        for (int i = 0; i < 100000000; i   ) {
            Math.random();
        }
        System.out.println(System.nanoTime() - oldTime);

        oldTime = System.nanoTime();
        for (int i = 0; i < 100000000; i   ) {
            qr.random();
        }
        System.out.println(System.nanoTime() - oldTime);
}

Sadece sayı "çift." sihirli bir önceki çift çarpar çok basit bir algoritma. Muhtemelen daha iyi bir hale getirebileceğimi bu yüzden birlikte çok hızlı bir şekilde attım, ama garip bir şekilde, iyi çalışıyor gibi görünüyor.

Bu yorumladı-out main yöntemi hatları örnek çıktı

0.612201846732229
0.5823974655091941
0.31062451498865684
0.8324473610354004
0.5907187526770246
0.38650264675748947
0.5243464344127049
0.7812828761272188
0.12417247811074805
0.1322738256858378
0.20614642573072284
0.8797579436677381
0.022122999476108518
0.2017298328387873
0.8394849894162446
0.6548917685640614
0.971667953190428
0.8602096647696964
0.8438709031160894
0.694884972852229

Hm. - Oldukça sıradan. Aslında, bu bir oyun rasgele sayı üreteci için çalışmaya devam eder.

Burada olmayan yorumladı kısım: örnek çıktı

5456313909
1427223941

Vay be! Neredeyse 4 kat daha hızlı Math.random daha gerçekleştirir.

Math.random System.nanoTime() deli modül ve bölünme ton malzeme kullanılan bir yerde okuduğumu hatırlıyorum. Bu gerçekten gerekli mi? Benim algoritma çok daha hızlı yapar ve oldukça rastgele görünüyor.

İki sorum var:

  • Benim algoritma "" (için, bir oyun, nerede söyle . yeterince iyi ^strong>gerçektenrasgele sayı) önemli değil mi?
  • Neden Math.random sadece basit bir çarpma görünüyor ve ondalık kesmek yeterli olacağı bu kadar mı?

CEVAP
24 Ocak 2013, PERŞEMBE


QuickRandom uygulaması, gerçekten düzgün bir dağıtım yok. Frekansları Math.random() daha düzgün bir dağıtım varken genelde daha düşük değerler daha yüksektir. İşte bunu gösteren SSCCE bir:

package com.stackoverflow.q14491966;

import java.util.Arrays;

public class Test {

    public static void main(String[] args) throws Exception {
        QuickRandom qr = new QuickRandom();
        int[] frequencies = new int[10];
        for (int i = 0; i < 100000; i  ) {
            frequencies[(int) (qr.random() * 10)]  ;
        }
        printDistribution("QR", frequencies);

        frequencies = new int[10];
        for (int i = 0; i < 100000; i  ) {
            frequencies[(int) (Math.random() * 10)]  ;
        }
        printDistribution("MR", frequencies);
    }

    public static void printDistribution(String name, int[] frequencies) {
        System.out.printf("%n%s distribution |8000     |9000     |10000    |11000    |12000%n", name);
        for (int i = 0; i < 10; i  ) {
            char[] bar = "                                                  ".toCharArray(); // 50 chars.
            Arrays.fill(bar, 0, Math.max(0, Math.min(50, frequencies[i] / 100 - 80)), '#');
            System.out.printf("0.%dxxx: m  :%s%n", i, frequencies[i], new String(bar));
        }
    }

}

Ortalama sonuç bu gibi görünüyor:

QR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  11376  :#################################                 
0.1xxx:  11178  :###############################                   
0.2xxx:  11312  :#################################                 
0.3xxx:  10809  :############################                      
0.4xxx:  10242  :######################                            
0.5xxx:   8860  :########                                          
0.6xxx:   9004  :##########                                        
0.7xxx:   8987  :#########                                         
0.8xxx:   9075  :##########                                        
0.9xxx:   9157  :###########                                       

MR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  10097  :####################                              
0.1xxx:   9901  :###################                               
0.2xxx:  10018  :####################                              
0.3xxx:   9956  :###################                               
0.4xxx:   9974  :###################                               
0.5xxx:  10007  :####################                              
0.6xxx:  10136  :#####################                             
0.7xxx:   9937  :###################                               
0.8xxx:  10029  :####################                              
0.9xxx:   9945  :###################    

Siz testi tekrarlayın eğer, QR dağıtım BAY dağıtım kararlı iken ağır, ilk tohumları bağlı olarak değişir, göreceksiniz. Bazen istediğiniz tek tip dağıtım ulaşır, ama çok sık değil. Burada daha uç örnekler, grafik sınırları bile aşar:

QR distribution |8000     |9000     |10000    |11000    |12000
0.0xxx:  41788  :##################################################
0.1xxx:  17495  :##################################################
0.2xxx:  10285  :######################                            
0.3xxx:   7273  :                                                  
0.4xxx:   5643  :                                                  
0.5xxx:   4608  :                                                  
0.6xxx:   3907  :                                                  
0.7xxx:   3350  :                                                  
0.8xxx:   2999  :                                                  
0.9xxx:   2652  :                                                  

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ELPRESADOR

    ELPRESADOR

    21 HAZİRAN 2008
  • PaulGBelliveau

    PaulGBellive

    5 Mart 2009
  • Stanislav Petrov

    Stanislav Pe

    7 ŞUBAT 2009