BlessRNG o pagsusi sa RNG alang sa kaangayan

BlessRNG o pagsusi sa RNG alang sa kaangayan

Sa pag-uswag sa dula, kanunay nimo kinahanglan nga ihigot ang usa ka butang nga adunay randomness: Ang Unity adunay kaugalingon nga Random alang niini, ug dungan niini adunay System.Random. Kaniadto, sa usa sa mga proyekto, nakuha nako ang impresyon nga ang duha mahimo nga magkalainlain nga trabaho (bisan kung sila kinahanglan adunay parehas nga pag-apod-apod).

Unya wala sila moadto sa mga detalye - igo na nga ang pagbalhin sa System.Random gitul-id ang tanan nga mga problema. Karon nakahukom kami nga susihon kini sa dugang nga detalye ug maghimo usa ka gamay nga panukiduki: kung unsa ang "bias" o matag-an nga mga RNG, ug kung kinsa ang pilion. Dugang pa, labaw pa sa usa ka higayon nakadungog ako nga nagkasumpaki nga mga opinyon bahin sa ilang "pagkamatinud-anon" - sulayan naton mahibal-an kung giunsa ang tinuud nga mga sangputanan kung itandi sa mga gipahayag.

Ang mubu nga programa sa edukasyon o RNG sa tinuud RNG

Kung pamilyar ka na sa mga random number generators, mahimo ka dayon nga molaktaw sa seksyon nga "Pagsulay".

Ang mga random nga numero (RN) usa ka han-ay sa mga numero nga namugna gamit ang pipila ka random (kagubot) nga proseso, usa ka gigikanan sa entropy. Sa ato pa, kini usa ka han-ay kansang mga elemento wala magkadugtong sa bisan unsang balaod sa matematika - wala silay hinungdan-ug-epekto nga relasyon.

Ang nagmugna sa random nga numero gitawag nga random number generator (RNG). Morag elementarya ang tanan, apan kung molihok kita gikan sa teorya hangtod sa praktis, nan sa tinuud dili kaayo yano ang pagpatuman sa usa ka algorithm sa software alang sa paghimo sa ingon nga pagkasunod-sunod.

Ang hinungdan mao ang pagkawala sa parehas nga kagubot sa modernong consumer electronics. Kung wala kini, ang mga random nga numero mohunong nga mahimong random, ug ang ilang generator nahimo nga usa ka ordinaryo nga function sa klaro nga gihubit nga mga argumento. Alang sa daghang mga espesyalista sa natad sa IT, kini usa ka seryoso nga problema (pananglitan, cryptography), apan alang sa uban adunay usa ka hingpit nga madawat nga solusyon.

Kinahanglan nga magsulat usa ka algorithm nga mobalik, bisan kung dili tinuud nga random nga mga numero, apan labi ka duol sa kanila - ang gitawag nga pseudo-random nga mga numero (PRN). Ang algorithm niini nga kaso gitawag nga pseudorandom number generator (PRNG).

Adunay ubay-ubay nga mga kapilian sa paghimo og PRNG, apan ang mosunod mahimong may kalabotan sa tanan:

  1. Ang panginahanglan alang sa preliminary initialization.

    Ang PRNG walay tinubdan sa entropy, mao nga kinahanglang hatagan kini ug inisyal nga kahimtang sa dili pa gamiton. Gipiho kini isip numero (o vector) ug gitawag nga liso (random nga liso). Kasagaran, ang processor clock counter o ang numerical equivalent sa system time kay gigamit isip liso.

  2. Pagkasunod-sunod nga reproducibility.

    Ang PRNG hingpit nga deterministiko, busa ang liso nga gipiho sa panahon sa pagsugod talagsaon nga nagtino sa tibuok umaabot nga han-ay sa mga numero. Kini nagpasabot nga ang usa ka separado nga PRNG nga gisugdan sa samang liso (sa lain-laing mga panahon, sa lain-laing mga programa, sa lain-laing mga himan) makamugna sa sama nga han-ay.

Kinahanglan usab nimo mahibal-an ang posibilidad nga pag-apod-apod nga naghulagway sa PRNG - unsa nga mga numero ang mamugna niini ug kung unsa ang posibilidad. Kasagaran kini usa ka normal nga pag-apod-apod o usa ka managsama nga pag-apod-apod.
BlessRNG o pagsusi sa RNG alang sa kaangayan
Normal nga distribution (wala) ug uniporme nga distribution (tuo)

Ingnon ta nga kita adunay patas nga mamatay nga adunay 24 ka kilid. Kung imo kining ilabay, ang kalagmitan nga makakuha ug usa mahimong katumbas sa 1/24 (parehas sa posibilidad nga makakuha ug lain nga numero). Kung maghimo ka daghang mga paglabay ug irekord ang mga resulta, imong mamatikdan nga ang tanan nga mga ngilit mahulog nga adunay parehas nga frequency. Sa tinuud, kini nga mamatay mahimong makonsiderar nga usa ka RNG nga adunay managsama nga pag-apod-apod.

Unsa kaha kung imong ilabay ang 10 niini nga mga dice sa usa ka higayon ug ihap ang kinatibuk-ang puntos? Mamentinar ba ang pagkaparehas niini? Dili. Kasagaran, ang kantidad mahimong duol sa 125 puntos, nga mao, sa pipila ka average nga kantidad. Ug ingon usa ka sangputanan, bisan sa wala pa maghimo usa ka paglabay, mahimo nimong mabanabana ang umaabot nga sangputanan.

Ang hinungdan mao nga adunay labing kadaghan nga mga kombinasyon aron makuha ang kasagaran nga marka. Ang mas layo gikan niini, ang mas diyutay nga mga kombinasyon - ug, sumala niana, mas ubos ang posibilidad sa pagkawala. Kung kini nga datos makita, kini dili klaro nga susama sa porma sa usa ka kampanilya. Busa, uban sa pipila ka pag-inat, ang usa ka sistema sa 10 dice mahimong tawgon nga RNG nga adunay normal nga pag-apod-apod.

Laing pananglitan, niining higayona sa usa ka eroplano - pagpamusil sa usa ka target. Ang shooter mahimong usa ka RNG nga makamugna og usa ka parisan sa mga numero (x, y) nga gipakita sa graph.
BlessRNG o pagsusi sa RNG alang sa kaangayan
Mouyon nga ang kapilian sa wala mas duol sa tinuod nga kinabuhi - kini usa ka RNG nga adunay normal nga pag-apod-apod. Apan kung kinahanglan nimo nga isabwag ang mga bituon sa usa ka ngitngit nga kalangitan, nan ang husto nga kapilian, nga nakuha gamit ang RNG nga adunay managsama nga pag-apod-apod, mas haum. Sa kinatibuk-an, pagpili sa usa ka generator depende sa buluhaton sa kamot.

Karon maghisgot kita bahin sa entropy sa han-ay sa PNG. Pananglitan, adunay usa ka han-ay nga nagsugod sama niini:

89, 93, 33, 32, 82, 21, 4, 42, 11, 8, 60, 95, 53, 30, 42, 19, 34, 35, 62, 23, 44, 38, 74, 36, 52, 18, 58, 79, 65, 45, 99, 90, 82, 20, 41, 13, 88, 76, 82, 24, 5, 54, 72, 19, 80, 2, 74, 36, 71, 9, ...

Unsa ka random kini nga mga numero sa unang pagtan-aw? Magsugod ta pinaagi sa pagsusi sa pag-apod-apod.
BlessRNG o pagsusi sa RNG alang sa kaangayan
Kini tan-awon nga duol sa uniporme, apan kung imong basahon ang usa ka han-ay sa duha ka mga numero ug hubaron kini isip mga coordinate sa usa ka eroplano, imong makuha kini:
BlessRNG o pagsusi sa RNG alang sa kaangayan
Ang mga sumbanan mahimong klaro nga makita. Ug tungod kay ang datos sa han-ay gimando sa usa ka piho nga paagi (nga mao, kini adunay ubos nga entropy), kini mahimong hinungdan sa maong "bias". Sa labing gamay, ang ingon nga PRNG dili kaayo angay alang sa paghimo og mga coordinate sa usa ka eroplano.

Laing pagkasunodsunod:

42, 72, 17, 0, 30, 0, 15, 9, 47, 19, 35, 86, 40, 54, 97, 42, 69, 19, 20, 88, 4, 3, 67, 27, 42, 56, 17, 14, 20, 40, 80, 97, 1, 31, 69, 13, 88, 89, 76, 9, 4, 85, 17, 88, 70, 10, 42, 98, 96, 53, ...

Ang tanan ingon og maayo dinhi bisan sa eroplano:
BlessRNG o pagsusi sa RNG alang sa kaangayan
Atong tan-awon ang gidaghanon (basaha ang tulo ka numero sa usa ka higayon):
BlessRNG o pagsusi sa RNG alang sa kaangayan
Ug pag-usab ang mga sumbanan. Dili na posible ang paghimo og visualization sa upat ka dimensyon. Apan ang mga sumbanan mahimong maglungtad sa kini nga dimensyon ug sa mas dako.

Sa cryptography, diin ang labing higpit nga mga kinahanglanon gipahamtang sa mga PRNG, ang ingon nga kahimtang dili gyud madawat. Busa, ang mga espesyal nga algorithm naugmad aron masusi ang ilang kalidad, nga dili na nato hikapon karon. Ang hilisgutan kay halapad ug angayan sa usa ka bulag nga artikulo.

Pagsulay

Kung wala kita nahibal-an nga sigurado, kung giunsa kini pagtrabaho? Takus ba ang pagtabok sa karsada kung wala ka mahibal-an kung unsang suga sa trapiko ang gitugotan? Ang mga sangputanan mahimong lahi.

Ang sama nga alang sa bantog nga randomness sa Unity. Maayo kung ang dokumentasyon nagpadayag sa gikinahanglan nga mga detalye, apan ang istorya nga gihisgutan sa sinugdanan sa artikulo nahitabo tungod sa kakulang sa gitinguha nga mga detalye.

Ug kung wala ka mahibal-an kung giunsa ang paglihok sa himan, dili nimo kini magamit sa husto. Sa kinatibuk-an, ang panahon miabut na sa pagsusi ug pagpahigayon sa usa ka eksperimento sa katapusan sa pagsiguro sa labing menos mahitungod sa pag-apod-apod.

Ang solusyon kay simple ug epektibo - pagkolekta sa estadistika, pagkuha og tumong nga datos ug tan-awa ang mga resulta.

Hilisgutan sa pagtuon

Adunay daghang mga paagi aron makamugna ang mga random nga numero sa Unity - gisulayan namon ang lima.

  1. System.Random.Next(). Naghimo og mga integer sa gihatag nga range sa mga kantidad.
  2. System.Random.NextDouble(). Naghimo og doble nga mga numero sa katukma sa range gikan sa [0; 1).
  3. UnityEngine.Random.Range(). Naghimo usa ka numero sa katukma (naglutaw) sa gihatag nga sakup sa mga kantidad.
  4. UnityEngine.Random.value. Naghimo og usa ka numero sa katukma (mga float) sa range gikan sa [0; 1).
  5. Unity.Mathematics.Random.NextFloat(). Kabahin sa bag-ong Unity.Mathematics library. Naghimo usa ka numero sa katukma (naglutaw) sa gihatag nga sakup sa mga kantidad.

Halos bisan asa sa dokumentasyon ang usa ka uniporme nga pag-apod-apod gipiho, gawas sa UnityEngine.Random.value (diin ang pag-apod-apod wala gitino, apan pinaagi sa analohiya sa UnityEngine.Random.Range() nga uniporme gipaabot usab) ug Unity.Mathematics.Random .NextFloat() (diin sa Ang basehan mao ang xorshift algorithm, nga nagpasabot nga pag-usab kinahanglan nimo nga maghulat alang sa usa ka uniporme nga pag-apod-apod).

Sa kasagaran, ang gipaabot nga mga resulta gikuha sama sa gipiho sa dokumentasyon.

Pamaagi

Gisulat namo ang usa ka gamay nga aplikasyon nga nakamugna og mga han-ay sa mga random nga numero gamit ang matag usa sa gipresentar nga mga pamaagi ug gitipigan ang mga resulta alang sa dugang nga pagproseso.

Ang gitas-on sa matag han-ay kay 100 ka numero.
Ang han-ay sa mga random nga numero mao ang [0, 100).

Ang datos nakolekta gikan sa daghang target nga mga plataporma:

  • Windows
    — Panaghiusa v2018.3.14f1, Editor mode, Mono, .NET Standard 2.0
  • macOS
    — Panaghiusa v2018.3.14f1, Editor mode, Mono, .NET Standard 2.0
    — Panaghiusa v5.6.4p4, Editor mode, Mono, .NET Standard 2.0
  • Android
    — Panaghiusa v2018.3.14f1, pagtukod matag aparato, Mono, .NET Standard 2.0
  • iOS
    — Panaghiusa v2018.3.14f1, pagtukod matag aparato, il2cpp, .NET Standard 2.0

Pagpatuman

Kita adunay daghang lain-laing mga paagi sa pagmugna ug random nga mga numero. Alang sa matag usa kanila, magsulat kami usa ka lahi nga klase sa wrapper, nga kinahanglan maghatag:

  1. Posibilidad sa pagtakda sa sakup sa mga kantidad [min/max). Itakda pinaagi sa constructor.
  2. Pamaagi sa pagbalik sa MF. Pilion nato ang float isip tipo, kay mas general kini.
  3. Ang ngalan sa pamaagi sa henerasyon alang sa pagmarka sa mga resulta. Alang sa kasayon, atong ibalik isip usa ka bili ang tibuok nga ngalan sa klase + ang ngalan sa pamaagi nga gigamit sa pagmugna sa MF.

Una, ipahayag nato ang abstraction nga irepresentar sa interface sa IRandomGenerator:

namespace RandomDistribution
{
    public interface IRandomGenerator
    {
        string Name { get; }

        float Generate();
    }
}

Pagpatuman sa System.Random.Next()

Kini nga pamaagi nagtugot kanimo sa pagtakda sa usa ka lain-laing mga bili, apan kini mobalik integers, apan floats gikinahanglan. Mahimo nimo nga hubaron ang integer ingon usa ka float, o mahimo nimong mapalapad ang sakup sa mga kantidad sa daghang mga order sa kadako, nga mabayran kini sa matag henerasyon sa midrange. Ang resulta mahimong usa ka butang nga sama sa usa ka fixed-point nga adunay gihatag nga han-ay sa katukma. Atong gamiton kini nga opsyon tungod kay mas duol kini sa tinuod nga float value.

using System;

namespace RandomDistribution
{
    public class SystemIntegerRandomGenerator : IRandomGenerator
    {
        private const int DefaultFactor = 100000;
        
        private readonly Random _generator = new Random();
        private readonly int _min;
        private readonly int _max;
        private readonly int _factor;


        public string Name => "System.Random.Next()";


        public SystemIntegerRandomGenerator(float min, float max, int factor = DefaultFactor)
        {
            _min = (int)min * factor;
            _max = (int)max * factor;
            _factor = factor;
        }


        public float Generate() => (float)_generator.Next(_min, _max) / _factor;
    }
}

Pagpatuman sa System.Random.NextDouble()

Dinhi ang pirmi nga sakup sa mga kantidad [0; 1). Aron ma-proyekto kini sa usa nga gipiho sa konstruktor, gigamit namon ang yano nga aritmetika: X * (max − min) + min.

using System;

namespace RandomDistribution
{
    public class SystemDoubleRandomGenerator : IRandomGenerator
    {
        private readonly Random _generator = new Random();
        private readonly double _factor;
        private readonly float _min;


        public string Name => "System.Random.NextDouble()";


        public SystemDoubleRandomGenerator(float min, float max)
        {
            _factor = max - min;
            _min = min;
        }


        public float Generate() => (float)(_generator.NextDouble() * _factor) + _min;
    }
}

Pagpatuman sa UnityEngine.Random.Range()

Kini nga pamaagi sa UnityEngine.Random static nga klase nagtugot kanimo sa pagtakda sa usa ka lain-laing mga kantidad ug ibalik ang usa ka float type. Dili kinahanglan nga mobuhat ka bisan unsang dugang nga pagbag-o.

using UnityEngine;

namespace RandomDistribution
{
    public class UnityRandomRangeGenerator : IRandomGenerator
    {
        private readonly float _min;
        private readonly float _max;


        public string Name => "UnityEngine.Random.Range()";


        public UnityRandomRangeGenerator(float min, float max)
        {
            _min = min;
            _max = max;
        }


        public float Generate() => Random.Range(_min, _max);
    }
}

Pagpatuman sa UnityEngine.Random.value

Ang value property sa static nga klase nga UnityEngine.Random nagbalik ug float type gikan sa fixed range sa values ​​[0; 1). Ato kining i-proyekto ngadto sa gihatag nga range sa samang paagi sama sa dihang nag-implementar sa System.Random.NextDouble().

using UnityEngine;

namespace RandomDistribution
{
    public class UnityRandomValueGenerator : IRandomGenerator
    {
        private readonly float _factor;
        private readonly float _min;


        public string Name => "UnityEngine.Random.value";


        public UnityRandomValueGenerator(float min, float max)
        {
            _factor = max - min;
            _min = min;
        }


        public float Generate() => (float)(Random.value * _factor) + _min;
    }
}

Pagpatuman sa Unity.Mathematics.Random.NextFloat()

Ang NextFloat() nga pamaagi sa Unity.Mathematics.Random nga klase nagbalik sa floating point sa type float ug nagtugot kanimo sa pagpiho sa lain-laing mga kantidad. Ang bugtong nuance mao nga ang matag instance sa Unity.Mathematics.Random kinahanglan nga magsugod sa pipila ka mga liso - niining paagiha malikayan nato ang paghimo og balik-balik nga mga han-ay.

using Unity.Mathematics;

namespace RandomDistribution
{
    public class UnityMathematicsRandomValueGenerator : IRandomGenerator
    {
        private Random _generator;
        private readonly float _min;
        private readonly float _max;


        public string Name => "Unity.Mathematics.Random.NextFloat()";


        public UnityMathematicsRandomValueGenerator(float min, float max)
        {
            _min = min;
            _max = max;
            _generator = new Random();
            _generator.InitState(unchecked((uint)System.DateTime.Now.Ticks));
        }


        public float Generate() => _generator.NextFloat(_min, _max);
    }
}

Pagpatuman sa MainController

Daghang mga pagpatuman sa IRandomGenerator ang andam na. Sunod, kinahanglan nimo nga makamugna og mga han-ay ug i-save ang resulta nga dataset alang sa pagproseso. Aron mahimo kini, maghimo kami usa ka talan-awon ug usa ka gamay nga script sa MainController sa Unity, nga buhaton ang tanan nga kinahanglan nga trabaho ug sa samang higayon mahimong responsable alang sa interaksyon sa UI.

Atong itakda ang gidak-on sa dataset ug ang han-ay sa mga kantidad sa MF, ug magkuha usab og pamaagi nga magbalik sa han-ay sa mga generator nga na-configure ug andam na sa pagtrabaho.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        private const int DefaultDatasetSize = 100000;

        public float MinValue = 0f;
        public float MaxValue = 100f;

        ...

        private IRandomGenerator[] CreateRandomGenerators()
        {
            return new IRandomGenerator[]
            {
                new SystemIntegerRandomGenerator(MinValue, MaxValue),
                new SystemDoubleRandomGenerator(MinValue, MaxValue),
                new UnityRandomRangeGenerator(MinValue, MaxValue),
                new UnityRandomValueGenerator(MinValue, MaxValue),
                new UnityMathematicsRandomValueGenerator(MinValue, MaxValue)
            };
        }

        ...
    }
}

Karon maghimo kita usa ka dataset. Sa kini nga kaso, ang paghimo sa datos ikombinar sa pagrekord sa mga resulta ngadto sa usa ka text stream (sa csv format). Aron matipigan ang mga kantidad sa matag IRandomGenerator, ang kaugalingon nga separado nga kolum gigahin, ug ang una nga linya naglangkob sa Ngalan sa generator.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        ...
		
        private void GenerateCsvDataSet(TextWriter writer, int dataSetSize, params IRandomGenerator[] generators)
        {
            const char separator = ',';
            int lastIdx = generators.Length - 1;

            // write header
            for (int j = 0; j <= lastIdx; j++)
            {
                writer.Write(generators[j].Name);
                if (j != lastIdx)
                    writer.Write(separator);
            }
            writer.WriteLine();

            // write data
            for (int i = 0; i <= dataSetSize; i++)
            {
                for (int j = 0; j <= lastIdx; j++)
                {
                    writer.Write(generators[j].Generate());
                    if (j != lastIdx)
                        writer.Write(separator);
                }

                if (i != dataSetSize)
                    writer.WriteLine();
            }
        }

        ...
    }
}

Ang nahabilin mao ang pagtawag sa GenerateCsvDataSet nga pamaagi ug i-save ang resulta sa usa ka file, o ibalhin dayon ang data sa network gikan sa katapusan nga aparato hangtod sa tigdawat nga server.

namespace RandomDistribution
{
    public class MainController : MonoBehaviour
    {
        ...
		
        public void GenerateCsvDataSet(string path, int dataSetSize, params IRandomGenerator[] generators)
        {
            using (var writer = File.CreateText(path))
            {
                GenerateCsvDataSet(writer, dataSetSize, generators);
            }
        }


        public string GenerateCsvDataSet(int dataSetSize, params IRandomGenerator[] generators)
        {
            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
            {
                GenerateCsvDataSet(writer, dataSetSize, generators);
                return writer.ToString();
            }
        }

        ...
    }
}

Ang mga tinubdan sa proyekto anaa sa GitLab.

Результаты

Walay milagro nga nahitabo. Ang ilang gipaabut mao ang ilang nakuha - sa tanan nga mga kaso, usa ka parehas nga pag-apod-apod nga wala’y timailhan sa mga panagkunsabo. Wala nako makita ang punto sa pagbutang og bulag nga mga graph para sa mga plataporma - silang tanan nagpakita sa gibana-bana nga parehas nga mga resulta.

Ang kamatuoran mao ang:
BlessRNG o pagsusi sa RNG alang sa kaangayan

Pagtan-aw sa mga han-ay sa usa ka eroplano gikan sa tanan nga lima ka henerasyon nga mga pamaagi:
BlessRNG o pagsusi sa RNG alang sa kaangayan

Ug visualization sa 3D. Ibilin ra nako ang resulta sa System.Random.Next() aron dili makagama og pundok sa parehas nga sulod.
BlessRNG o pagsusi sa RNG alang sa kaangayan

Ang istorya nga giasoy sa pasiuna bahin sa normal nga pag-apod-apod sa UnityEngine.Random wala mag-usab sa iyang kaugalingon: bisan kini sa sinugdan sayup, o adunay nausab sukad sa makina. Apan karon sigurado na kami.

Source: www.habr.com

Idugang sa usa ka comment