এটি কি "যথেষ্ট যথেষ্ট" এলোমেলোভাবে অ্যালগরিদম; এটি দ্রুত হলে এটি ব্যবহার করা হয় না কেন?


171

আমি বলা একটি ক্লাস তৈরি করেছি QuickRandom, এবং এর কাজটি দ্রুত এলোমেলো সংখ্যা তৈরি করা। এটি সত্যই সহজ: পুরানো মানটি ধরুন, একটি দিয়ে গুণ করুনdouble , এবং দশমিক অংশ নিন।

এখানে আমার QuickRandomক্লাস সম্পূর্ণরূপে:

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

}

এটি পরীক্ষা করার জন্য আমি এখানে কোড লিখেছি:

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

এটি একটি খুব সাধারণ অ্যালগরিদম যা কেবল "ম্যাজিক সংখ্যা" দ্বিগুণ দ্বারা পূর্ববর্তী ডাবলকে গুণ করে। আমি এটি খুব দ্রুত একসাথে ছুঁড়েছি, তাই আমি সম্ভবত এটি আরও ভাল করতে পারি, তবে আশ্চর্যের বিষয়, এটি ঠিকঠাকভাবে কাজ করছে বলে মনে হচ্ছে।

এটি পদ্ধতিতে মন্তব্য-আউট লাইনের নমুনা আউটপুট main:

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

হুঁ। বেশ এলোমেলো। আসলে, এটি একটি গেমের এলোমেলো সংখ্যা জেনারেটরের জন্য কাজ করবে।

এখানে অ-মন্তব্য করা অংশের নমুনা আউটপুট দেওয়া হল:

5456313909
1427223941

কি দারুন! এটি প্রায় 4 গুণ বেশি দ্রুত পারফর্ম করেMath.random

আমার মনে আছে পড়া কোথাও যে Math.randomব্যবহৃত System.nanoTime()এবং পাগল মডুলাস এবং বিভাজন জিনিস রয়েছে। সত্যিই প্রয়োজন? আমার অ্যালগরিদম অনেক দ্রুত সম্পাদন করে এবং এটি বেশ এলোমেলো মনে হয়।

আমার দুটি প্রশ্ন আছে:

  • আমার অ্যালগরিদম কি "যথেষ্ট ভাল" (যেমন, একটি গেম, যেখানে সত্যিকারের এলোমেলো সংখ্যা খুব গুরুত্বপূর্ণ নয়)?
  • Math.randomযখন কেবল সহজ গুণ এবং দশমিক ছাড়াই যথেষ্ট হবে বলে মনে হয় কেন এত বেশি কাজ করে?

154
"বেশ এলোমেলো মনে হচ্ছে"; আপনার একটি হিস্টোগ্রাম তৈরি করা উচিত এবং আপনার ক্রম অনুসারে কিছু স্বতঃসংশোধন চালানো উচিত ...
অলিভার চার্লসওয়ার্থ

63
তার অর্থ "মনে হচ্ছে" বেশ এলোমেলো "আসলে এলোমেলোতার কোনও উদ্দেশ্য পরিমাপ নয় এবং আপনার কিছু বাস্তব পরিসংখ্যান পাওয়া উচিত।
ম্যাট এইচ

23
@ ডুরকনব: সাধারণ ব্যক্তির শর্তে, আপনার সংখ্যাগুলি 0 থেকে 1 এর মধ্যে "সমতল" বিতরণ রয়েছে কিনা তা খতিয়ে দেখা উচিত এবং সময়ের সাথে সাথে পর্যায়ক্রমিক / পুনরাবৃত্তিমূলক নিদর্শন রয়েছে কিনা তা দেখুন।
অলিভার চার্লসওয়ার্থ

22
চেষ্টা করুন new QuickRandom(0,5)বা new QuickRandom(.5, 2)। তারা উভয় বার বার আপনার সংখ্যা জন্য 0 আউটপুট হবে।
ফ্র্যাঙ্কি TheKneeMan

119
আপনার নিজের এলোমেলো সংখ্যা জেনারেশন অ্যালগরিদম লেখার মতো আপনার নিজের এনক্রিপশন অ্যালগরিদম লেখার মতো। হাইপার-যোগ্য ব্যক্তিদের দ্বারা এখানে অনেক পূর্বের শিল্প রয়েছে যে এটি সঠিক করার জন্য আপনার সময় ব্যয় করা বোকামি। জাভা লাইব্রেরির ফাংশনগুলি ব্যবহার না করার কোনও কারণ নেই এবং যদি আপনি সত্যিই কোনও কারণে নিজের লেখা লিখতে চান তবে উইকিপিডিয়ায় যান এবং সেখানে মেসার্ন টুইস্টারের মতো আলগোরিদিমগুলি সন্ধান করুন।
স্টিভেহা

উত্তর:


351

আপনার QuickRandomবাস্তবায়নের সত্যই অভিন্ন বিতরণ নেই। ফ্রিকোয়েন্সিগুলি নিম্নতর মানগুলিতে সাধারণত বেশি থাকে এবং Math.random()আরও সমান বিতরণ থাকে। এখানে একটি এসএসসিসি রয়েছে যা দেখায় যে:

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: %6d  :%s%n", i, frequencies[i], new String(bar));
        }
    }

}

গড় ফলস্বরূপ দেখতে:

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  :###################    

আপনি যদি পরীক্ষার পুনরাবৃত্তি করেন, আপনি দেখতে পাবেন যে এমআর বিতরণ স্থিতিশীল থাকা অবস্থায় প্রাথমিক বীজের উপর নির্ভর করে কিউআর বিতরণ খুব বেশি পরিবর্তিত হয়। কখনও কখনও এটি পছন্দসই ইউনিফর্ম বিতরণে পৌঁছায় তবে প্রায়শই বেশি এটি হয় না। এখানে আরও চরম উদাহরণগুলির মধ্যে একটি, এটি এমনকি গ্রাফের সীমানার বাইরেও রয়েছে:

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  :                                                  

17
সংখ্যাগত ডেটার জন্য +1 - যদিও কাঁচা সংখ্যাগুলি অনুসন্ধান করা বিভ্রান্তিকর হতে পারে কারণ এর অর্থ এই নয় যে তাদের পরিসংখ্যানগত দিক থেকে গুরুত্বপূর্ণ পার্থক্য রয়েছে।
ম্যাকিয়েজ পাইচোটকা

16
এই ফলাফলগুলি প্রাথমিক বীজগুলিতে প্রেরণের সাথে ব্যাপকভাবে পরিবর্তিত হয় QuickRandom। কখনও কখনও, এটি ইউনিফর্মের কাছাকাছি, কখনও কখনও এটি এর চেয়ে আরও খারাপ।
পেট্রা জেনেয়েক

68
@ ব্লুরাজা-ড্যানিফ্লুঘুফুট যে কোনও পিআরএনজি যেখানে আউটপুটটির মান প্রাথমিক বীজের মান (অভ্যন্তরীণ স্থিতির বিপরীতে) এর উপর নির্ভর করে তা আমার কাছে ভাঙা মনে হচ্ছে।
একটি সিভিএন

22
পরিসংখ্যানের প্রথম নিয়ম: ডেটা প্লট করুন । আপনার বিশ্লেষণ স্পট-অন, কিন্তু একটি হিস্টগ্রামের প্লট করা এটিকে আরও দ্রুত দেখায়। ;-) (এবং এটি আর। এর দুটি লাইন)
কনরাড রুডল্ফ

37
বাধ্যতামূলক উদ্ধৃতি: "যে কেউ এলোমেলো অঙ্ক তৈরির পাটিগণিত পদ্ধতি বিবেচনা করে সে অবশ্যই পাপের অবস্থায় রয়েছে।" - জন ভন নিউমান (১৯৫১) "যে কেউ কমপক্ষে ১০০ জায়গায় উপরের উদ্ধৃতিটি দেখেননি তিনি সম্ভবত খুব বেশি বয়সী নন।" - ডিভি প্রায়ার (1993) "এলোমেলোভাবে সংখ্যার জেনারেটর নির্বাচন করা উচিত নয়।" - ডোনাল্ড নুথ (1986)
হ্যাপি গ্রিন কিড নেপস

133

আপনি যা বর্ণনা করছেন তা হ'ল এক প্রকার র্যান্ডম জেনারেটর যাকে লিনিয়ার কংগ্রেসিভ জেনারেটর বলে । জেনারেটর নিম্নলিখিত হিসাবে কাজ করে:

  • একটি বীজ মান এবং গুণক দিয়ে শুরু করুন।
  • একটি এলোমেলো সংখ্যা তৈরি করতে:
    • গুণক দ্বারা বীজ গুণ করুন।
    • এই মানের সমান বীজ সেট করুন।
    • এই মানটি ফেরত দিন।

এই জেনারেটরের অনেক দুর্দান্ত বৈশিষ্ট্য রয়েছে, তবে একটি ভাল এলোমেলো উত্স হিসাবে উল্লেখযোগ্য সমস্যা রয়েছে। উপরে লিঙ্কিত উইকিপিডিয়া নিবন্ধে কিছু শক্তি এবং দুর্বলতা বর্ণনা করা হয়েছে। সংক্ষেপে, আপনার যদি ভাল এলোমেলো মানগুলির প্রয়োজন হয় তবে এটি সম্ভবত খুব ভাল পদ্ধতির নয়।

আশাকরি এটা সাহায্য করবে!


@ লুইজম- এটি সত্যিকার অর্থে "এলোমেলো" নয়। ফলাফলগুলি নির্বিচারক হবে। এটি বলেছিল, আমার উত্তর লেখার সময় আমি সে সম্পর্কে ভেবে দেখিনি; সম্ভবত কেউ এই বিস্তারিত ব্যাখ্যা করতে পারেন?
টেম্পলেটটিফাইফ

2
ভাসমান পয়েন্টের গাণিতিক ত্রুটিগুলি বাস্তবায়নের নকশা করা হয়। যতদূর আমি জানি, এগুলি একটি নির্দিষ্ট প্ল্যাটফর্মের জন্য সামঞ্জস্যপূর্ণ তবে বিভিন্ন মোবাইল ফোন এবং পিসি আর্কিটেকচারের মধ্যে যেমন পৃথক হতে পারে। যদিও একসাথে ধারাবাহিকভাবে ভাসমান পয়েন্ট গণনা করার সময় অতিরিক্ত 'গার্ড বিটস' যুক্ত হয় এবং এই গার্ড বিটের উপস্থিতি বা অনুপস্থিতি ফলাফলকে গণনাটি আলাদাভাবে আলাদা করতে পারে। (প্রহরী বিটস, যেমন,
bit৪

2
এছাড়াও, মনে রাখবেন যে LCRNGs এর পিছনের তত্ত্বটি ধরেই নেয় যে আপনি পূর্ণসংখ্যার সাথে কাজ করছেন! এ ফ্লোটিং পয়েন্ট সংখ্যার নিক্ষেপ করবে না ফলাফলের একই মানের ফলন হয়।
ডাস্কউফ-অ্যাক্টিভটিভ-

1
@ ডাস্কউফ, আপনি ঠিক বলেছেন তবে যদি ভাসমান পয়েন্ট হার্ডওয়্যার বুদ্ধিমানের নিয়মগুলি অনুসরণ করে তবে এটি করা ম্যান্টিসার আকারটিকে মোডুল করা সমান এবং তত্ত্বটি প্রয়োগ হয়। আপনি যা করছেন তার জন্য কেবল অতিরিক্ত যত্নের প্রয়োজন।
ভনব্র্যান্ড

113

আপনার এলোমেলো সংখ্যার ফাংশনটি দরিদ্র, কারণ এতে খুব কম অভ্যন্তরীণ অবস্থা রয়েছে - যে কোনও পদক্ষেপে ফাংশনটির দ্বারা আউটপুটটি পুরোপুরি পূর্ববর্তী সংখ্যার উপর নির্ভরশীল dependent উদাহরণস্বরূপ, আমরা যদি ধরে নিই যে magicNumberএটি 2 (উদাহরণস্বরূপ), তবে ক্রম:

0.10 -> 0.20

অনুরূপ ক্রম দ্বারা দৃ strongly়ভাবে মিরর করা হয়:

0.09 -> 0.18
0.11 -> 0.22

অনেক ক্ষেত্রে, এটি আপনার গেমটিতে লক্ষণীয় পারস্পরিক সম্পর্ক তৈরি করবে - উদাহরণস্বরূপ, আপনি যদি আপনার ক্রিয়ায় অবজেক্টগুলির জন্য এক্স এবং ওয়াই স্থানাঙ্ক জেনারেশন করার জন্য ক্রমাগত কল করেন তবে অবজেক্টগুলি স্পষ্ট তির্যক নিদর্শন তৈরি করবে।

আপনার যদি বিশ্বাস করার পক্ষে যুক্তিসঙ্গত কারণ না থাকে যে এলোমেলো সংখ্যা জেনারেটর আপনার অ্যাপ্লিকেশনটি কমিয়ে দিচ্ছে (এবং এটি খুব সম্ভবত সম্ভাবনা নেই), নিজের চেষ্টা করার এবং লেখার কোনও উপযুক্ত কারণ নেই।


36
ব্যবহারিক উত্তরের জন্য +1 ... এটিকে একটি অঙ্কুরের জন্য ব্যবহার করুন এবং মহাকাব্যিক একাধিক শিরোনামগুলির জন্য তির্যকগুলি শত্রুগুলিকে ছড়িয়ে দিন? : ডি
উইম

@ উইম: আপনি যদি এমন নিদর্শন চান তবে আপনার কোনও পিআরএনজি লাগবে না।
মিথ্যা রায়ান

109

এর সাথে আসল সমস্যাটি হ'ল এটির আউটপুট হিস্টগ্রাম প্রাথমিক বীজের উপর অনেক বেশি নির্ভর করে - বেশিরভাগ সময় এটি প্রায় অভিন্ন আউটপুট দিয়ে শেষ হয় তবে বেশিরভাগ সময় স্বতন্ত্রভাবে ইউনিফর্ম আউটপুট থাকে।

দ্বারা অনুপ্রাণিত কিভাবে খারাপ পিএইচপি এর এই নিবন্ধটি rand()ফাংশন , আমি কিছু র্যান্ডম ম্যাট্রিক্স চিত্র ব্যবহার করেছেন QuickRandomএবং System.Random। এই রানটি দেখায় যে কখনও কখনও বীজের কীভাবে খারাপ প্রভাব ফেলতে পারে (এক্ষেত্রে নিম্ন সংখ্যার পক্ষে) যেখানে System.Randomবেশ অভিন্ন।

QuickRandom

System.Random

আরো খারাপ

আমরা ইনিশিয়ালাইজ তাহলে QuickRandomযেমন new QuickRandom(0.01, 1.03)আমরা এই চিত্রটি পাবেন:

কোড

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace QuickRandomTest
{
    public class QuickRandom
    {
        private double prevNum;
        private readonly double magicNumber;

        private static readonly Random rand = new Random();

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

        public QuickRandom()
            : this(rand.NextDouble(), rand.NextDouble() * 10)
        {
        }

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

    class Program
    {
        static void Main(string[] args)
        {
            var rand = new Random();
            var qrand = new QuickRandom();
            int w = 600;
            int h = 600;
            CreateMatrix(w, h, rand.NextDouble).Save("System.Random.png", ImageFormat.Png);
            CreateMatrix(w, h, qrand.Random).Save("QuickRandom.png", ImageFormat.Png);
        }

        private static Image CreateMatrix(int width, int height, Func<double> f)
        {
            var bitmap = new Bitmap(width, height);
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    var c = (int) (f()*255);
                    bitmap.SetPixel(x, y, Color.FromArgb(c,c,c));
                }
            }

            return bitmap;
        }
    }
}

2
চমৎকার কোড। হ্যাঁ, এটি দুর্দান্ত। আমি এটিও মাঝে মাঝে করতাম, এর থেকে পরিমাণের পরিমাপ পাওয়া শক্ত, তবে ক্রমটি দেখার জন্য এটি আরও ভাল উপায়। এবং আপনি যদি প্রস্থ * উচ্চতার চেয়ে দীর্ঘের ক্রমগুলির সন্ধান করতে চান তবে আপনি এই চিত্রটি প্রতি পিক্সেল-পিক্সেল সহ পরবর্তী চিত্রটি জোর করতে পারেন। আমি মনে করি কুইকআরন্ডম ছবিটি আরও বেশি নান্দনিকভাবে আনন্দদায়ক, যদিও এটি সামুদ্রিক উইন্ড কার্পেটের মতো টেক্সচারযুক্ত কারণে।
ক্রিস স্ট্রিংফেলো

নন্দনতাত্ত্বিকভাবে আনন্দদায়ক অংশটি হ'ল আপনি প্রতিটি সারি বরাবর যাওয়ার পরে ক্রমটি কীভাবে বাড়তে থাকে (এবং তারপরে আবার শুরুতে ফিরে আসে) কারণ magicNumberগুণটি একই সংখ্যার উত্পাদন করে prevNumযা এলোমেলোতার অভাব দেখায়। আমরা যদি বীজ ব্যবহার করি new QuickRandom(0.01, 1.03)তবে আমরা এই i.imgur.com/Q1Yunbe.png পাই !
কলম রজার্স

হ্যাঁ, দুর্দান্ত বিশ্লেষণ। যেহেতু এটি মোড মোড হওয়ার আগে ধীরে ধীরে পরিষ্কারভাবে 1 দ্বারা গুণিত হয় সেখানে আপনার বর্ণনা বৃদ্ধি পাবে। দেখে মনে হয় যে আমরা যদি 1 বিলিয়ন গুন করে মোড একটি 256 রঙ প্যালেট হ্রাস করে উল্লেখযোগ্য পরিমাণে দশমিক প্ল্যাকিংগুলি গ্রহণ করি তবে এটিকে এড়ানো সম্ভব।
ক্রিস স্ট্রিংফেলো

আপনি কি আমাকে বলতে পারবেন যে এই আউটপুট চিত্রগুলি তৈরি করতে আপনি কী ব্যবহার করেছেন? মতলব?
উদয়

@ ইউডাওয়াই: কোডটি একবার দেখুন, সি # এবং System.Drawing.Bitmap
কলম্ব রজার্স

37

আপনার এলোমেলো নম্বর জেনারেটরের একটি সমস্যা হ'ল কোনও 'লুকানো অবস্থা' নেই - যদি আমি জানতাম যে আপনি শেষ কলটিতে কোন র্যান্ডম নম্বরটি ফিরে এসেছেন, আমি জানি প্রতিটি একক র্যান্ডম নম্বর আপনি সময়ের শেষে অবধি পাঠিয়ে দেবেন, যেহেতু কেবলমাত্র একটিই আছে সম্ভাব্য পরবর্তী ফলাফল, এবং আরও অনেক কিছু।

আরেকটি বিষয় বিবেচনা করার জন্য হ'ল আপনার এলোমেলো নম্বর জেনারেটরের 'পিরিয়ড'। স্পষ্টতই একটি সীমাবদ্ধ রাষ্ট্র আকারের সাথে ডাবলের মান্টিসা অংশের সমান, এটি লুপিংয়ের আগে সর্বাধিক 2 ^ 52 মানগুলি ফিরিয়ে দিতে সক্ষম হবে। তবে এটি সর্বোত্তম ক্ষেত্রে - আপনি কি প্রমাণ করতে পারবেন যে 1, 2, 3, 4 পিরিয়ডের কোনও লুপ নেই ...? যদি তা থাকে তবে আপনার আরএনজির ক্ষেত্রে সেই পরিস্থিতিতে ভয়ঙ্কর, অধঃপতিত আচরণ হবে।

তদতিরিক্ত, আপনার এলোমেলো সংখ্যা প্রজন্মের সমস্ত সূচনা পয়েন্টগুলির জন্য অভিন্ন বিতরণ থাকবে? যদি এটি না হয়, তবে আপনার আরএনজি পক্ষপাতদুষ্ট হবে - বা আরও খারাপ, প্রারম্ভিক বীজের উপর নির্ভর করে বিভিন্ন উপায়ে পক্ষপাতযুক্ত।

আপনি যদি এই সমস্ত প্রশ্নের উত্তর দিতে পারেন, দুর্দান্ত। যদি আপনি না পারেন তবে আপনি জানেন যে কেন বেশিরভাগ লোকেরা চাকাটি পুনরায় উদ্ভাবন করে না এবং প্রমাণিত এলোমেলো সংখ্যা জেনারেটর ব্যবহার করে না;)

(যাইহোক, একটি ভাল প্রবাদটি হ'ল: দ্রুততম কোডটি এমন কোড কোড যা চলমান না You আপনি বিশ্বের দ্রুততম র্যান্ডম () তৈরি করতে পারেন, তবে এটি খুব এলোমেলো না হলে এটি কোনও ভাল নয়))


8
সব বীজ এই জেনারেটরের উপর অন্তত একটি তুচ্ছ লুপ: 0 -> 0। বীজের উপর নির্ভর করে আরও অনেকে থাকতে পারে। (উদাহরণস্বরূপ, একটি 3.0 বীজ, সঙ্গে জন্য 0.5 -> 0.5, 0.25 -> 0.75 -> 0.25, 0.2 -> 0.6 -> 0.8 -> 0.4 -> 0.2ইত্যাদি,)
-inactive- duskwuff

36

PRNGs বিকাশ করার সময় আমি সর্বদা একটি সাধারণ পরীক্ষা করতাম:

  1. আউটপুটকে চর মানগুলিতে রূপান্তর করুন
  2. একটি ফাইলের অক্ষর মান লিখুন
  3. ফাইল সঙ্কুচিত করুন

এটি আমাকে প্রায় 1 থেকে 20 মেগাবাইটের অনুক্রমের জন্য "যথেষ্ট ভাল" পিআরএনজি ছিল এমন ধারণাগুলিতে পুনরাবৃত্তি করতে দেয়। এটি কেবল চোখের দ্বারা পরীক্ষা করে দেখার চেয়ে আরও ভাল উপরে ডাউন ছবি দিয়েছে কারণ অর্ধ-শব্দ শর্তযুক্ত কোনও "পিআরএনজি" চক্র পয়েন্টটি দেখার জন্য আপনার চোখের সক্ষমতা দ্রুত ছাড়িয়ে যেতে পারে।

আমি যদি সত্যিই বাছাই করতাম তবে আমি ভাল অ্যালগরিদমগুলি নিতে পারি এবং তাদের উপর ডিআইএইআরডিডি / এনআইএসটি পরীক্ষা চালাতে পারি, আরও অন্তর্দৃষ্টি পেতে, এবং তারপরে ফিরে গিয়ে আরও কিছু টুইট করতে পারি।

কম্প্রেশন টেস্টের সুবিধা, যেমন একটি ফ্রিকোয়েন্সি বিশ্লেষণের বিপরীতে, তুচ্ছভাবে এটি একটি ভাল বিতরণ তৈরি করা সহজ: কেবলমাত্র 256 দৈর্ঘ্যের ব্লকটি 0 - 255 এর সমস্ত অক্ষরের সমন্বয় করে এবং এটি 100,000 বার করে 100 তবে এই ক্রমের দৈর্ঘ্য 256 রয়েছে।

একটি স্কিউড বিতরণ, এমনকি একটি ছোট ব্যবধানে, একটি সংক্ষেপণ অ্যালগরিদম দ্বারা বাছাই করা উচিত, বিশেষত যদি আপনি এটির সাথে কাজ করার ক্রমটির যথেষ্ট পরিমাণ (1 মেগাবাইট বলে) দেন। যদি কিছু অক্ষর বা বিগ্রাম, বা এন-গ্রাম আরও ঘন ঘন ঘটে, তবে একটি সংক্ষেপণ অ্যালগরিদম সংক্ষিপ্ত কোড শব্দের সাথে ঘন ঘন ঘটনাকে পছন্দ করে এমন কোডগুলিতে এই বিতরণটিকে স্কোর করে এনকোড করতে পারে এবং আপনি সংকোচনের একটি ব-দ্বীপ পাবেন।

যেহেতু বেশিরভাগ সংক্ষেপণ অ্যালগরিদমগুলি দ্রুত, এবং তাদের কোনও প্রয়োগকরণের প্রয়োজন নেই (যেমন ওএসগুলি কেবল তাদের চারপাশে শুয়ে রয়েছে), তাই আপনার বিকাশমান কোনও পিআরএনজির জন্য দ্রুত রেটিং পাস / ব্যর্থতার জন্য সংক্ষেপণ পরীক্ষাটি খুব কার্যকর।

আপনার পরীক্ষাগুলির জন্য শুভকামনা!

ওহ, আমি আপনার কোডের নীচের ছোট মোড ব্যবহার করে আপনার উপরে থাকা আরএনজিতে এই পরীক্ষাটি করেছি:

import java.io.*;

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

    public static void main(String[] args) throws Exception {
        QuickRandom qr = new QuickRandom();
        FileOutputStream fout = new FileOutputStream("qr20M.bin");

        for (int i = 0; i < 20000000; i ++) {
            fout.write((char)(qr.random()*256));
        }
    }
}

ফলাফলগুলি ছিল:

Cris-Mac-Book-2:rt cris$ zip -9 qr20M.zip qr20M.bin2
adding: qr20M.bin2 (deflated 16%)
Cris-Mac-Book-2:rt cris$ ls -al
total 104400
drwxr-xr-x   8 cris  staff       272 Jan 25 05:09 .
drwxr-xr-x+ 48 cris  staff      1632 Jan 25 05:04 ..
-rw-r--r--   1 cris  staff      1243 Jan 25 04:54 QuickRandom.class
-rw-r--r--   1 cris  staff       883 Jan 25 05:04 QuickRandom.java
-rw-r--r--   1 cris  staff  16717260 Jan 25 04:55 qr20M.bin.gz
-rw-r--r--   1 cris  staff  20000000 Jan 25 05:07 qr20M.bin2
-rw-r--r--   1 cris  staff  16717402 Jan 25 05:09 qr20M.zip

আউটপুট ফাইলটি মোটেই সংকুচিত করা না গেলে আমি একটি পিআরএনজি ভাল বিবেচনা করব। সত্যি কথা বলতে, আমি ভাবিনি যে আপনার পিআরএনজি এত ভাল করবে, কেবলমাত্র% 20 ডলারে মেগস এমন একটি সাধারণ নির্মাণের জন্য বেশ চিত্তাকর্ষক। তবে আমি এখনও এটিকে ব্যর্থ বলে বিবেচনা করি।


2
ইমেজিং করুন বা না করুন, আমি আমার এলোমেলো জেনারেটর পরীক্ষা করার পরে আমার জিপগুলির সাথে একই ধারণা ছিল।
এরিস্টোস

1
ধন্যবাদ @ আলেকজান্দ্রে সি। এবং অ্যারিস্টোস এবং এডিয়ান। আমি তোমাকে বিশ্বাস করি.
ক্রিস স্ট্রিংফেলো

33

আপনি যে দ্রুততম র্যান্ডম জেনারেটরটি প্রয়োগ করতে পারেন তা হ'ল:

এখানে চিত্র বর্ণনা লিখুন

এক্সডি, রসিকতা বাদে সবকিছু এখানে বলেছিল, আমি উল্লেখ করে অবদান রাখতে চাই যে এলোমেলো ক্রমগুলি পরীক্ষা করা "একটি কঠিন কাজ" [1], এবং সিডো-এলোমেলো সংখ্যার কয়েকটি বৈশিষ্ট্য যাচাই করে এমন কয়েকটি পরীক্ষা রয়েছে, আপনি এটি খুঁজে পেতে পারেন এগুলির অনেকগুলি এখানে: http://www.random.org/analysis/#2005

র্যান্ডম জেনারেটর "গুণমান" মূল্যায়নের একটি সহজ উপায় হ'ল পুরানো চি স্কোয়ার পরীক্ষা।

static double chisquare(int numberCount, int maxRandomNumber) {
    long[] f = new long[maxRandomNumber];
    for (long i = 0; i < numberCount; i++) {
        f[randomint(maxRandomNumber)]++;
    }

    long t = 0;
    for (int i = 0; i < maxRandomNumber; i++) {
        t += f[i] * f[i];
    }
    return (((double) maxRandomNumber * t) / numberCount) - (double) (numberCount);
}

উদ্ধৃতি [1]

পরীক্ষার ধারণাটি উত্পাদিত সংখ্যাগুলি যুক্তিসঙ্গতভাবে ছড়িয়ে পড়েছে কিনা তা যাচাই করা। আমরা যদি আর এর চেয়ে কম এন ধনাত্মক সংখ্যা উত্পন্ন করি , তবে আমরা এন / আর সম্পর্কে আশা করব প্রতিটি মানের নম্বর । তবে --- এবং এই বিষয়টির সারমর্ম --- সমস্ত মূল্যবোধের ঘনত্বের ফ্রিকোয়েন্সিগুলি ঠিক একই রকম হওয়া উচিত নয়: এটি এলোমেলো হবে না!

আমরা প্রত্যাশিত ফ্রিকোয়েন্সি দ্বারা ছোট করে প্রতিটি মান সংঘটিত হওয়ার ফ্রিকোয়েন্সিগুলির স্কোয়ারের যোগফলটি গণনা করি এবং তারপরে ক্রমের আকারটি বাদ রাখি। এই সংখ্যা, "χ² পরিসংখ্যান" গাণিতিক হিসাবে প্রকাশ করা যেতে পারে

চি স্কোয়ার সূত্র

যদি χ² পরিসংখ্যানগুলি r এর কাছাকাছি থাকে তবে সংখ্যাগুলি এলোমেলো হয়; যদি এটি খুব বেশি দূরে থাকে তবে তারা তা নয়। "নিকট" এবং "খুব দূরে" এর ধারণাগুলি আরও সুনির্দিষ্টভাবে সংজ্ঞায়িত করা যেতে পারে: টেবিলগুলি উপস্থিত রয়েছে যা র্যান্ডম সিকোয়েন্সগুলির বৈশিষ্ট্যগুলির সাথে পরিসংখ্যানকে ঠিক কীভাবে সম্পর্কিত তা বলে। যে সহজ পরীক্ষাটি আমরা সম্পাদন করছি তার জন্য পরিসংখ্যানগুলি 2√r এর মধ্যে হওয়া উচিত

এই তত্ত্ব এবং নিম্নলিখিত কোড ব্যবহার করে:

abstract class RandomFunction {
    public abstract int randomint(int range); 
}

public class test {
    static QuickRandom qr = new QuickRandom();

    static double chisquare(int numberCount, int maxRandomNumber, RandomFunction function) {
        long[] f = new long[maxRandomNumber];
        for (long i = 0; i < numberCount; i++) {
            f[function.randomint(maxRandomNumber)]++;
        }

        long t = 0;
        for (int i = 0; i < maxRandomNumber; i++) {
            t += f[i] * f[i];
        }
        return (((double) maxRandomNumber * t) / numberCount) - (double) (numberCount);
    }

    public static void main(String[] args) {
        final int ITERATION_COUNT = 1000;
        final int N = 5000000;
        final int R = 100000;

        double total = 0.0;
        RandomFunction qrRandomInt = new RandomFunction() {
            @Override
            public int randomint(int range) {
                return (int) (qr.random() * range);
            }
        }; 
        for (int i = 0; i < ITERATION_COUNT; i++) {
            total += chisquare(N, R, qrRandomInt);
        }
        System.out.printf("Ave Chi2 for QR: %f \n", total / ITERATION_COUNT);        

        total = 0.0;
        RandomFunction mathRandomInt = new RandomFunction() {
            @Override
            public int randomint(int range) {
                return (int) (Math.random() * range);
            }
        };         
        for (int i = 0; i < ITERATION_COUNT; i++) {
            total += chisquare(N, R, mathRandomInt);
        }
        System.out.printf("Ave Chi2 for Math.random: %f \n", total / ITERATION_COUNT);
    }
}

আমি নিম্নলিখিত ফলাফল পেয়েছি:

Ave Chi2 for QR: 108965,078640
Ave Chi2 for Math.random: 99988,629040

কুইকআরডম এর জন্য আর থেকে খুব দূরে (বাইরে r ± 2 * sqrt(r))

এটি বলা হয়েছিল, কুইকআরন্ডম দ্রুত হতে পারে তবে (অন্য উত্তরে বলা হয়েছে) এলোমেলো সংখ্যা জেনারেটর হিসাবে ভাল নয়


[1] সেডগুইক রবার্ট, সি ইন অ্যালগরিদম , অ্যাডিনসন ওয়েসলি পাবলিশিং সংস্থা, 1990, পৃষ্ঠা 516 থেকে 518


9
এক্সকিডির জন্য +1 যা একটি আশ্চর্যজনক ওয়াবসাইট (ওহ, এবং দুর্দান্ত উত্তর): পি
tckmn

1
ধন্যবাদ, এবং হ্যাঁ এক্সকেসিডি র্যাকস! এক্সডি
হাইগুয়ারো

তত্ত্বটি ঠিক আছে তবে সম্পাদন খুব কম: কোডটি পূর্ণসংখ্যার ওভারফ্লোতে সংবেদনশীল ti জাভাতে সমস্ত int[]শূন্যে আরম্ভ করা হয়, সুতরাং এই অংশের প্রয়োজন নেই। আপনি যখন ডাব্লু / ডাবলসের কাজ করেন তখন ভাসাতে কাস্ট করা অর্থহীন। শেষ: পদ্ধতিগুলির নামগুলি এলোমেলো 1 এবং র্যান্ডম 2 কল করা বেশ মজাদার is
বেটসেস

@ বেস্টেস পর্যবেক্ষণের জন্য ধন্যবাদ! আমি সি কোড থেকে সরাসরি অনুবাদ করেছি এবং এতে খুব বেশি মনোযোগ
দিইনি

14

আমি একত্র করা আপনার আলগোরিদিম একটি দ্রুত উপহাস-আপ ফলাফল নির্ণয় করা জাভাস্ক্রিপ্ট হবে। এটি 0 - 99 থেকে 100,000 এলোমেলো পূর্ণসংখ্যার উত্পন্ন করে এবং প্রতিটি পূর্ণসংখ্যার উদাহরণ ট্র্যাক করে।

প্রথম যে বিষয়টি আমি লক্ষ্য করি তা হ'ল আপনি উচ্চ সংখ্যার চেয়ে কম সংখ্যক পাওয়ার সম্ভাবনা বেশি। আপনি এটিকে সর্বাধিক দেখতে পাবেন যখন seed1উচ্চ এবং seed2কম থাকে। দু'বার উদাহরণে আমি পেয়েছি মাত্র 3 নম্বর।

সর্বোপরি, আপনার অ্যালগরিদমের কিছু সংশোধন প্রয়োজন।


8

যদি Math.Random()ফাংশন অপারেটিং সিস্টেমটিকে দিনের সময় পাওয়ার জন্য কল করে তবে আপনি এটিকে আপনার ফাংশনের সাথে তুলনা করতে পারবেন না। আপনার ফাংশনটি একটি পিআরএনজি, যেখানে সেই ফাংশনটি সত্যিকারের এলোমেলো সংখ্যার জন্য চেষ্টা করে। আপেল এবং কমলা

আপনার PRNG দ্রুত হতে পারে, তবে এর পুনরাবৃত্তি হওয়ার আগে দীর্ঘ মেয়াদ অর্জনের জন্য পর্যাপ্ত রাষ্ট্রীয় তথ্য নেই (এবং এর যুক্তি এমনকি রাষ্ট্রের তথ্যের সাহায্যে সম্ভব সময়সীমা অর্জনের পক্ষে যথেষ্ট পরিশীলিত নয়)।

পিআরএনজি নিজেই পুনরাবৃত্তি শুরু করার আগে পিরিয়ডটি ক্রমের দৈর্ঘ্য। PRNG মেশিন একটি রাজ্যে রাষ্ট্রের রূপান্তর করার সাথে সাথে এটি ঘটে যা কিছু অতীতের রাজ্যের অনুরূপ। সেখান থেকে, এটি সেই রাজ্যে শুরু হওয়া রূপান্তরগুলির পুনরাবৃত্তি করবে। পিআরএনজি'র সাথে আর একটি সমস্যা হ'ল স্বল্প সংখ্যক অনন্য সিক্যুয়েন্সের পাশাপাশি কোনও নির্দিষ্ট ক্রমটির পুনরাবৃত্তি ঘটায় তা হ্রাস করতে পারে। অবাঞ্ছিত নিদর্শনও থাকতে পারে। উদাহরণস্বরূপ, ধরুন যে একটি পিআরএনজি সংখ্যার দশমিক ছাপানো হয় তখন মোটামুটি এলোমেলো দেখায়, তবে বাইনারিতে মানগুলি পরীক্ষা করে দেখা যায় যে বিট 4 প্রতিটি কলটিতে কেবল 0 এবং 1 এর মধ্যে টোগল করছে। ওহো!

মার্সেন টুইস্টার এবং অন্যান্য অ্যালগরিদমগুলি একবার দেখুন। পিরিয়ড দৈর্ঘ্য এবং সিপিইউ চক্রের মধ্যে ভারসাম্য রক্ষার উপায় রয়েছে। একটি মৌলিক পদ্ধতির (মার্সেন ট্যুইস্টারে ব্যবহৃত) হ'ল রাষ্ট্র ভেক্টরকে ঘিরে। এর অর্থ হ'ল, যখন একটি সংখ্যা তৈরি করা হচ্ছে, তখন এটি পুরো রাজ্যের উপর ভিত্তি করে তৈরি হয় না, কেবলমাত্র রাজ্য অ্যারে থেকে কিছু শব্দে কিছু বিট কাজ করে। তবে প্রতিটি পদক্ষেপে অ্যালগরিদম অ্যারেতেও ঘুরে বেড়ায়, একবারে সামগ্রীগুলি সামান্য স্ক্র্যাম করে ling


5
আপনার প্রথম অনুচ্ছেদ ব্যতীত আমি বেশিরভাগ ক্ষেত্রেই একমত। অন্তর্নির্মিত র্যান্ডম কলগুলি (এবং ইউনিক্সের মতো সিস্টেমে / dev / এলোমেলো) এছাড়াও পিআরএনজি s আমি এমন কোনও কল করব যা অ্যালগোরিদমিকভাবে একটি পিআরএনজি তৈরি করে, এমনকি বীজ এমন কিছু হয় যা পূর্বাভাস দেওয়াও কঠিন। কয়েকটি "সত্য" র্যান্ডম সংখ্যার জেনারেটর রয়েছে যা তেজস্ক্রিয় ক্ষয়, বায়ুমণ্ডলীয় শব্দ ইত্যাদি ব্যবহার করে তবে এগুলি প্রায়শই তুলনামূলকভাবে কয়েকটি বিট / সেকেন্ড উত্পন্ন করে।
ম্যাট ক্রাউস

লিনাক্স বাক্সগুলিতে, /dev/randomডিভাইস ড্রাইভারদের কাছ থেকে প্রাপ্ত সত্যিকারের এলোমেলোতার উত্স, এবং পিআরএনজি নয়। পর্যাপ্ত বিট পাওয়া না গেলে এটি ব্লক করে দেয়। বোনের ডিভাইসটিও /dev/urandomব্লক করে না, তবে এটি এখনও কোনও পিআরএনজি নয় কারণ এটি উপলভ্য র্যান্ডম বিটগুলি আপডেট করা হয়।
কাজ

যদি ম্যাথ.র্যান্ডম () ফাংশন অপারেটিং সিস্টেমটিকে দিনের সময় পাওয়ার জন্য কল করে - এটি একেবারেই অসত্য। (আমি জানি জাভা স্বাদ / সংস্করণগুলির মধ্যে
কোনওটি

@ বেস্টেস এটি মূল প্রশ্নটি থেকে: আমি কোথাও পড়ে মনে পড়ছি যে ম্যাথ.রান্ডম সিস্টেম.নানোটাইম () ব্যবহার করেছিল । আপনার জ্ঞানটি সেখানে বা আপনার উত্তরে যুক্ত হতে পারে। আমি শর্তসাপেক্ষে যদি এটি ব্যবহার করে থাকি । :)
কাজ

কাজ, উভয় nanoTime()+ কাউন্টার / হ্যাশ java.util.Randomওরাকল / ওপেনজেডিকে- র ডিফল্ট বীজের জন্য ব্যবহৃত হয় । এটি তখনই বীজের জন্য হয় এটি একটি স্ট্যান্ডার্ড এলসিজি। কার্যত ওপি জেনারেটর বীজের জন্য 2 টি এলোমেলো সংখ্যা নেয় যা ঠিক আছে - সুতরাং এর চেয়ে কোনও পার্থক্য নেই java.util.RandomSystem.currentTimeMillis()JDK1.4- এ প্রথম বীজ ছিল
1:

7

সেখানে অনেকগুলি, বহু ছদ্ম এলোমেলো সংখ্যা জেনারেটর রয়েছে। উদাহরণস্বরূপ Knuth এর জন্য ranarray , Mersenne প্রতারক , অথবা LFSR জেনারেটর দেখুন। নুথের স্মৃতিচিহ্ন "সেমুনিউমেরিয়াল অ্যালগোরিদম" অঞ্চলটিকে বিশ্লেষণ করে এবং কিছু লিনিয়ার কংগ্রেসিভ জেনারেটর প্রস্তাব করে (কার্যকর করার জন্য সহজ, দ্রুত)।

তবে আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি কেবলমাত্র আটকে থাকুন java.util.Randomবা Math.random, এগুলি দ্রুত এবং অন্তত মাঝে মধ্যে ব্যবহারের জন্য ঠিক আছে (যেমন, গেমস এবং এ জাতীয়) OK আপনি যদি বিতরণে কিছুটা ভৌতিক হয়ে থাকেন (কিছু মন্টি কার্লো প্রোগ্রাম, বা জেনেটিক অ্যালগরিদম), তাদের প্রয়োগগুলি পরীক্ষা করুন (উত্সটি কোথাও উপলব্ধ) এবং আপনার অপারেটিং সিস্টেম থেকে বা র্যান্ডম. org থেকে কিছু সত্যিকারের এলোমেলো সংখ্যার সাথে সেগুলি বীজ করুন । এটি যদি এমন কোনও অ্যাপ্লিকেশনের জন্য প্রয়োজন যেখানে সুরক্ষা গুরুতর, আপনি নিজেই খনন করতে হবে। এবং সেই ক্ষেত্রে আপনার বিশ্বাস করা উচিত নয় যে এখানে কিছু গা colored় বিট স্পাউট রয়েছে এমন রঙিন স্কোয়ারটি আমি এখন বন্ধ করব।


7

Randomএকাধিক থ্রেড থেকে একক উদাহরণ অ্যাক্সেস না করে আপনি যে কোনও ব্যবহার-ক্ষেত্রে এলে এলোমেলো সংখ্যা জেনারেশন পারফরম্যান্স একটি সমস্যা হয়ে দাঁড়াবে এটি খুব সম্ভব নয় isRandom এটি synchronized)

তবে, যদি সত্যিই এটি হয় এবং আপনার যদি প্রচুর এলোমেলো সংখ্যক দ্রুত প্রয়োজন হয় তবে আপনার সমাধানটি খুব বেশি বিশ্বাসযোগ্য নয়। কখনও কখনও এটি ভাল ফলাফল দেয়, কখনও কখনও ভয়ঙ্কর দেয় ফলাফল (প্রাথমিক সেটিংসের ভিত্তিতে)।

আপনি যদি Randomক্লাসটি দেয় একই নম্বর চান তবে কেবল দ্রুত, আপনি সেখানে সিঙ্ক্রোনাইজেশন থেকে মুক্তি পেতে পারেন:

public class QuickRandom {

    private long seed;

    private static final long MULTIPLIER = 0x5DEECE66DL;
    private static final long ADDEND = 0xBL;
    private static final long MASK = (1L << 48) - 1;

    public QuickRandom() {
        this((8682522807148012L * 181783497276652981L) ^ System.nanoTime());
    }

    public QuickRandom(long seed) {
        this.seed = (seed ^ MULTIPLIER) & MASK;
    }

    public double nextDouble() {
        return (((long)(next(26)) << 27) + next(27)) / (double)(1L << 53);
    }

    private int next(int bits) {
        seed = (seed * MULTIPLIER + ADDEND) & MASK;
        return (int)(seed >>> (48 - bits));
    }

}

আমি কেবল java.util.Randomকোডটি নিয়েছি এবং সিঙ্ক্রোনাইজেশনটি সরিয়েছি যা আমার ওরাকল হটস্পট জেভিএম 7u9 এর মূল তুলনায় দ্বিগুণ পারফরম্যান্সের ফলস্বরূপ। এটি আপনার তুলনায় এখনও ধীর QuickRandom, তবে এটি আরও বেশি ধারাবাহিক ফলাফল দেয়। সুনির্দিষ্টভাবে বলতে গেলে, একই seedমান এবং একক থ্রেডেড অ্যাপ্লিকেশনগুলির জন্য, এটি মূল ক্লাসের মতো একই সিউডো-এলোমেলো সংখ্যা দেয় Random


এই কোডটি java.util.Randomওপেনজেডকে 7 ইউ- তে বর্তমানের ভিত্তিতে রয়েছে যা জিএনইউ জিপিএল ভি 2 এর অধীন লাইসেন্সপ্রাপ্ত ।


সম্পাদনা 10 মাস পরে:

আমি সবেমাত্র আবিষ্কার করেছি যে একটি অযৌক্তিক Randomউদাহরণ পেতে আপনাকে উপরের আমার কোডটি ব্যবহার করতে হবে না । জেডিকেও আছে!

জাভা 7 এর ThreadLocalRandomক্লাস দেখুন। এর ভিতরে থাকা কোডটি আমার উপরের কোডের সাথে প্রায় একই। ক্লাসটি কেবল স্থানীয়-থ্রেড-বিচ্ছিন্ন Randomসংস্করণ যা এলোমেলো সংখ্যা দ্রুত তৈরি করার জন্য উপযুক্ত। আমি কেবলমাত্র খারাপ দিকটিই ভাবতে পারি তা হ'ল আপনি seedনিজে এটি সেট করতে পারবেন না ।

ব্যবহারের উদাহরণ:

Random random = ThreadLocalRandom.current();

2
@ এডিট হুম, আমি যখন খুব বেশি অলস না হই তখন আমি কিউআর, ম্যাথ.আরেন্ডম এবং থ্রেডলোক্যালর্যান্ডমের তুলনা করতে পারি :)যে আকর্ষণীয়, ধন্যবাদ!
tckmn

1. সর্বাধিক 16 বিট ব্যবহৃত বিটগুলিকে প্রভাবিত করে না বলে আপনি মাস্কটি ফেলে দিয়ে আরও কিছু গতি অর্জন করতে পারেন। ২. আপনি এই বিটগুলি ব্যবহার করতে পারেন, একটি বিয়োগ সংরক্ষণ করতে পারেন এবং আরও ভাল জেনারেটর পেতে পারেন (বৃহত্তর রাষ্ট্র; একটি পণ্যের সর্বাধিক উল্লেখযোগ্য বিটগুলি খুব সুন্দরভাবে বিতরণ করা হয় তবে কিছু মূল্যায়নের প্রয়োজন হবে)। ৩. সূর্যের ছেলেরা সহজেই নুথের দ্বারা একটি প্রত্নতাত্ত্বিক আরএনজি প্রয়োগ করেছিল এবং সংশ্লেষ যুক্ত করেছে। :(
মার্টিনাস

3

'র্যান্ডম' নাম্বার পাওয়ার চেয়ে আরও বেশি কিছু .... আপনার যা আছে তা সিউডো-এলোমেলো

যদি সিউডো-এলোমেলোভাবে আপনার উদ্দেশ্যগুলির জন্য যথেষ্ট ভাল, তবে নিশ্চিত হয়ে নিন যে এটি দ্রুততর হয় (এবং এক্সওর + বিটশিফ্ট আপনার যা আছে তার চেয়ে দ্রুত হবে)

রল্ফ

সম্পাদনা:

ঠিক আছে, এই উত্তরে খুব তাড়াহুড়ো হওয়ার পরে, আপনার কোডটি আরও দ্রুত করার আসল কারণ সম্পর্কে আমাকে উত্তর দিন:

ম্যাথ.র্যান্ডম () এর জাভাডোক থেকে

একাধিক থ্রেড দ্বারা সঠিক ব্যবহারের অনুমতি দেওয়ার জন্য এই পদ্ধতিটি সঠিকভাবে সিঙ্ক্রোনাইজ করা হয়েছে। তবে, যদি অনেক থ্রেডকে দুর্দান্ত হারে সিউডোরডম সংখ্যা উত্পন্ন করার প্রয়োজন হয়, তবে এটি প্রতিটি থ্রেডের নিজস্ব সিউডোরেন্ডম-নম্বর জেনারেটর রাখার জন্য বিতর্ক হ্রাস করতে পারে।

আপনার কোডটি দ্রুত হওয়ার কারণে এটি সম্ভবত।


3
খুব সুন্দর যে কোনও কিছু যা কোনও হার্ডওয়্যার শোনার জেনারেটর বা ওএসের আই / ও স্টাফের মধ্যে একটি সরাসরি লাইন জড়িত না, তা ছদ্ম-এলোমেলো হতে চলেছে। জেনুইন এলোমেলোতা একা একটি অ্যালগোরিদম দ্বারা উত্পন্ন করা যায় না; আপনার কোথাও থেকে গোলমাল দরকার। (কিছু
ওএসের আরএনজি

@ অলিচার্লসওয়ার্থ: সত্যই, আমি যতদূর জানি একমাত্র সত্যিকারের এলোমেলো মানগুলি বায়ুমণ্ডলীয় গোলমাল ব্যবহার করে পাওয়া যায়।
জেরোইন ভেনেভেল

@ ম ... তাড়াতাড়ি উত্তর দিতে বোকা। ম্যাথ.র্যান্ডম সিউডোরানডম এবং এটিও সিঙ্ক্রোনাইজ করা হয়
রলফ্ল

@rolfl: সুসংগতকরণ খুব Math.random()ধীরে ধীরে ব্যাখ্যা করতে পারে যে কেন ধীর। এটি হয় প্রতিবার সিঙ্ক্রোনাইজ বা একটি নতুন তৈরি করতে হবে Randomএবং কারও খুব আকর্ষণীয় পারফরম্যান্সের দিক দিয়ে নয়। আমি যদি পারফরম্যান্সের বিষয়ে চিন্তা করি তবে আমি নিজের তৈরি করব new Randomএবং এটি ব্যবহার করব। : পি
সিএইচও

@ জিরোভানভেনিল তেজস্ক্রিয় ক্ষয় এলোমেলোও।
আরএক্সএস

3

java.util.Random খুব আলাদা নয়, নূথ বর্ণিত একটি প্রাথমিক এলসিজি। তবে এর প্রধান 2 প্রধান সুবিধা / পার্থক্য রয়েছে:

  • থ্রেড নিরাপদ - প্রতিটি আপডেট হ'ল একটি সিএএস যা সাধারণ লেখার চেয়ে বেশি ব্যয়বহুল এবং এর একটি শাখা প্রয়োজন (এমনকি সিগেল থ্রেডেডের পূর্বাভাস দেওয়া হলেও)। সিপিইউর উপর নির্ভর করে এটি উল্লেখযোগ্য পার্থক্য হতে পারে।
  • অপ্রকাশিত অভ্যন্তরীণ অবস্থা - অপ্রয়োজনীয় কোনও কিছুর জন্য এটি অত্যন্ত গুরুত্বপূর্ণ। আপনি চান এলোমেলো সংখ্যা অনুমানযোগ্য না হয়।

এর নীচে জাভা.ইটিল.র্যান্ডম-এ 'এলোমেলো' পূর্ণসংখ্যার উত্স প্রস্তুত করার মূল রুটিন।


  protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
          oldseed = seed.get();
          nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

আপনি যদি অ্যাটমিকলং এবং অঘোষিত সেটটি (যেমন সমস্ত বিট ব্যবহার করে long) সরিয়ে ফেলেন তবে আপনি দ্বিগুণ গুণ / মডুলোর চেয়ে বেশি পারফরম্যান্স পাবেন।

শেষ দ্রষ্টব্য: Math.randomসাধারণ পরীক্ষাগুলি ব্যতীত অন্য কোনও কিছুর জন্য ব্যবহার করা উচিত নয়, এটি ঝুঁকির ঝুঁকির প্রবণতা এবং যদি আপনার কাছে এটির একত্রে দু'ধরনের থ্রেডও বলা হয় তবে কর্মক্ষমতা হ্রাস পায়। এর একটি সামান্য পরিচিত historicalতিহাসিক বৈশিষ্ট্য হল জাভাতে সিএএসের পরিচিতি - একটি কুখ্যাত বেঞ্চমার্ককে পরাস্ত করা (প্রথমে আইবিএম দ্বারা অন্তর্নিবেশের মাধ্যমে এবং পরে সান "জাভা থেকে সিএএস" তৈরি করেছিলেন)


0

এটি আমার গেমগুলির জন্য আমি র্যান্ডম ফাংশনটি ব্যবহার করি। এটি বেশ দ্রুত এবং এর বিতরণ ভাল (যথেষ্ট) রয়েছে।

public class FastRandom {

    public static int randSeed;

      public static final int random()
      {
        // this makes a 'nod' to being potentially called from multiple threads
        int seed = randSeed;

        seed    *= 1103515245;
        seed    += 12345;
        randSeed = seed;
        return seed;
      }

      public static final int random(int range)
      {
        return ((random()>>>15) * range) >>> 17;
      }

      public static final boolean randomBoolean()
      {
         return random() > 0;
      }

       public static final float randomFloat()
       {
         return (random()>>>8) * (1.f/(1<<24));
       }

       public static final double randomDouble() {
           return (random()>>>8) * (1.0/(1<<24));
       }
}

1
এটি প্রশ্নের উত্তর সরবরাহ করে না। কোনও লেখকের কাছ থেকে সমালোচনা বা স্পষ্টতার জন্য অনুরোধ জানাতে, তাদের পোস্টের নীচে একটি মন্তব্য দিন।
জন উইলেমস

আমি মনে করি এটি ইতিমধ্যে প্রতিষ্ঠিত হয়েছিল যে মূল অ্যালগরিদম যথেষ্ট ভাল নয়? সম্ভবত যথেষ্ট ভাল একটি উদাহরণ কিভাবে এটি উন্নতি করতে অনুপ্রেরণা হতে পারে?
তেরজে

হ্যাঁ, হতে পারে, তবে এটি প্রশ্নের মোটেও উত্তর দেয় না এবং আপনার অ্যালগরিদমকে সমর্থন করার কোনও তথ্য আসলে "যথেষ্ট যথেষ্ট" নয়। সাধারণত, এলোমেলো সংখ্যার অ্যালগরিদম এবং ঘনিষ্ঠভাবে সম্পর্কিত এনক্রিপশন অ্যালগরিদমগুলি কোনও বিশেষজ্ঞের দ্বারা প্রোগ্রামিং ভাষায় প্রয়োগ করে never সুতরাং, আপনি যদি নিজের দাবির পক্ষে সমর্থন করতে পারেন এবং কেন প্রশ্নটির অ্যালগরিদমের চেয়ে এটি ভাল, তবে আপনি কমপক্ষে জিজ্ঞাসিত একটি প্রশ্নের উত্তর দিতে পারেন।
জন উইলেমস

ভাল ... বিশেষজ্ঞরা তাদের প্রোগ্রামিং ভাষায় প্রয়োগ করেছেন "নিখুঁত" বিতরণের লক্ষ্যে, যদিও একটি গেমের ক্ষেত্রে আপনার কখনই এটির প্রয়োজন হয় না। আপনি গতি, এবং "যথেষ্ট ভাল" বিতরণ চান। এই কোডটি এই অফার করে। যদি এটি এখানে অনুপযুক্ত হয় তবে আমি উত্তরটি মুছব, কোনও সমস্যা নেই।
তেরজে

মাল্টিথ্রেডিং সম্পর্কিত, স্থানীয় ভেরিয়েবলের আপনার ব্যবহারটি কোনও অপ-বিকল্প নয়, যেমনটি বাদে, volatileসংকলক ইচ্ছামত স্থানীয় ভেরিয়েবলগুলি (বা পরিচয় করিয়ে দিতে) মুক্ত করতে পারেন free
মার্টিনাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.