BlessRNG nó seiceáil an RNG le haghaidh cothroime

BlessRNG nó seiceáil an RNG le haghaidh cothroime

I bhforbairt cluiche, is minic go gcaithfidh tú rud éigin a cheangal suas le randamacht: tá a Randamach féin ag Unity le haghaidh seo, agus ag an am céanna leis tá System.Random. Uair amháin, ar cheann de na tionscadail, fuair mé an tuiscint go bhféadfadh an dá rud oibriú ar bhealach difriúil (cé gur cheart dáileadh cothrom a bheith acu).

Ansin níor chuaigh siad isteach i sonraí - ba leor gur cheartaigh an t-aistriú go System.Random na fadhbanna go léir. Anois bheartaíomar breathnú air go mion agus beagán taighde a dhéanamh: cé chomh “claonta” nó intuartha atá na RNGanna, agus cé acu ceann le roghnú. Thairis sin, tá níos mó ná uair amháin cloiste agam tuairimí contrártha faoina “macántacht” - déanaimis iarracht a dhéanamh amach conas a dhéanann na torthaí fíor i gcomparáid leis na cinn dearbhaithe.

Is RNG é clár oideachais gairid nó RNG

Má tá tú eolach ar ghineadóirí uimhreacha randamacha cheana féin, is féidir leat scipeáil láithreach chuig an rannán “Tástáil”.

Is seicheamh uimhreacha iad uimhreacha randamacha (RN) a ghintear trí úsáid a bhaint as próiseas randamach (chaotic) éigin, foinse eantrópachta. Is é sin, is seicheamh é seo nach bhfuil a eilimintí idirnasctha ag aon dlí matamaitice - níl gaol idir cúis agus éifeacht acu.

Gineadóir uimhreacha randamacha (RNG) a thugtar ar an rud a chruthaíonn an uimhir randamach. Is cosúil go bhfuil gach rud bunúsach, ach má bhogaimid ó theoiric go cleachtas, ansin i ndáiríre níl sé chomh simplí algartam bogearraí a chur i bhfeidhm chun seicheamh den sórt sin a ghiniúint.

Is é an chúis atá leis sin ná nach bhfuil an chaos céanna i leictreonaice tomhaltóra nua-aimseartha. Gan é, scoirfidh uimhreacha randamacha de bheith randamach, agus iompaíonn a gineadóir ina ghnáthfheidhm d'argóintí atá sainmhínithe go soiléir. I gcás roinnt speisialtachtaí sa réimse TF, is fadhb thromchúiseach é seo (mar shampla, cripteagrafaíocht), ach do dhaoine eile tá réiteach iomlán inghlactha.

Is gá algartam a scríobh a chuirfeadh ar ais, cé nach fíoruimhreacha randamacha iad, ach chomh gar agus is féidir dóibh - na huimhreacha bréagacha randamacha (PRN). Gineadóir uimhreacha pseudorandom (PRNG) a thugtar ar an algartam sa chás seo.

Tá go leor roghanna ann chun PRNG a chruthú, ach beidh na nithe seo a leanas ábhartha do gach duine:

  1. An gá atá le réamhthosú.

    Níl aon fhoinse eantrópachta ag an PRNG, mar sin ní mór staid tosaigh a thabhairt dó roimh úsáid. Sonraítear é mar uimhir (nó veicteoir) agus tugtar síol (síol randamach) air. Go minic, úsáidtear cuntar clog an phróiseálaí nó an choibhéis uimhriúil d’am córais mar shíol.

  2. In-atáirgtheacht seicheamh.

    Tá an PRNG go hiomlán cinntitheach, mar sin is é an síol a shonraítear le linn thúsaithe a chinneann seicheamh iomlán na n-uimhreacha amach anseo go uathúil. Ciallaíonn sé seo go gcruthóidh PRNG ar leith a cuireadh tús leis an síol céanna (ag amanna éagsúla, i gcláir éagsúla, ar ghléasanna éagsúla) an t-ord céanna.

Ní mór duit fios a bheith agat freisin ar an dáileadh dóchúlachta atá mar thréith ag an PRNG - cad iad na huimhreacha a ghinfidh sé agus cén dóchúlacht. Is minic gur dáileadh gnáth nó dáileadh aonfhoirmeach é seo.
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Dáileadh gnáth (ar chlé) agus dáileadh aonfhoirmeach (ar dheis)

Ligean le rá go bhfuil bás cothrom againn le 24 thaobh. Má chaitheann tú é, beidh an dóchúlacht go bhfaighidh tú ceann cothrom le 1/24 (mar an gcéanna leis an dóchúlacht go bhfaighidh tú aon uimhir eile). Má dhéanann tú go leor caitheamh agus má dhéanann tú na torthaí a thaifeadadh, tabharfaidh tú faoi deara go dtiteann na himill go léir amach thart ar an minicíocht chéanna. Go bunúsach, is féidir an dísle seo a mheas mar RNG le dáileadh aonfhoirmeach.

Cad a tharlóidh má chaitheann tú 10 gcinn de na dísle seo ag an am céanna agus na pointí iomlána a chomhaireamh? An gcoimeádfar aonfhoirmeacht dó? Níl. Is minic, beidh an méid gar do 125 pointe, is é sin, go dtí roinnt meánluach. Agus mar thoradh air sin, fiú sula ndéanann tú caith, is féidir leat meastachán garbh a dhéanamh ar an toradh amach anseo.

Is é an chúis atá leis ná go bhfuil an líon is mó comhcheangail ann chun an meánscór a fháil. Dá fhaide uaidh, is lú comhcheangail - agus, dá réir sin, is lú an dóchúlacht go dtarlóidh caillteanas. Má dhéantar na sonraí seo a léirshamhlú, beidh sé cosúil go doiléir le cruth clog. Dá bhrí sin, le roinnt stráice, is féidir córas 10 dísle a dtugtar RNG le dáileadh gnáth.

Sampla eile, ach an uair seo ar eitleán - lámhach ag sprioc. RNG a bheidh sa lámhachóir a ghineann péire uimhreacha (x, y) a thaispeánfar ar an ngraf.
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Aontaigh go bhfuil an rogha ar an taobh clé níos gaire don saol fíor - is RNG é seo le dáileadh gnáth. Ach más gá duit réaltaí a scaipeadh sa spéir dorcha, is fearr an rogha ceart, a fhaightear trí úsáid a bhaint as RNG le dáileadh aonfhoirmeach. Go ginearálta, roghnaigh gineadóir ag brath ar an tasc atá ar láimh.

Anois, déanaimis labhairt faoi eantrópacht na seicheamh PNG. Mar shampla, tá seicheamh ann a thosaíonn mar seo:

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, ...

Cé chomh randamach is atá na huimhreacha seo ar an gcéad amharc? Let tús le seiceáil an dáileadh.
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Breathnaíonn sé gar don éide, ach má léann tú seicheamh de dhá uimhir agus má léirmhíníonn tú iad mar chomhordanáidí ar eitleán, gheobhaidh tú é seo:
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Éiríonn patrúin le feiceáil go soiléir. Agus ós rud é go n-ordaítear na sonraí sa seicheamh ar bhealach áirithe (is é sin, go bhfuil eantrópacht íseal aige), is féidir go n-eascródh an “laofacht” sin as seo. Ar a laghad, níl a leithéid de PRNG an-oiriúnach chun comhordanáidí a ghiniúint ar eitleán.

Seicheamh eile:

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, ...

Is cosúil go bhfuil gach rud go breá anseo fiú ar an eitleán:
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Breathnaímid i méid (léigh trí uimhir ag an am):
BlessRNG nó seiceáil an RNG le haghaidh cothroime
Agus arís na patrúin. Ní féidir léirshamhlú a dhéanamh i gceithre thoise a thuilleadh. Ach is féidir patrúin a bheith ann ar an ngné seo agus ar chinn níos mó.

I gcás cripteagrafaíochta, i gcás ina bhforchuirtear na ceanglais is déine ar PRNGanna, tá cás den sórt sin do-ghlactha go catagóiriúil. Dá bhrí sin, forbraíodh halgartaim speisialta chun a gcáilíocht a mheas, rud nach mbeidh muid i dteagmháil leo anois. Is ábhar fairsing é agus tá alt ar leith tuillte aige.

Tástáil

Mura bhfuil a fhios againn go cinnte, conas a bheith ag obair leis? An fiú an bóthar a thrasnú mura bhfuil a fhios agat cé acu solas tráchta a cheadaíonn é? Féadfaidh na hiarmhairtí a bheith difriúil.

Baineann an rud céanna leis an randamacht iomráiteach in Unity. Tá sé go maith má nochtann an doiciméadú na sonraí riachtanacha, ach tharla an scéal a luadh ag tús an ailt go beacht mar gheall ar easpa na sonraí a bhí ag teastáil.

Agus mura bhfuil a fhios agat conas a oibríonn an uirlis, ní bheidh tú in ann é a úsáid i gceart. Go ginearálta, tá an t-am tagtha chun turgnamh a sheiceáil agus a dhéanamh chun a chinntiú ar deireadh ar a laghad faoin dáileadh.

Bhí an réiteach simplí agus éifeachtach - staitisticí a bhailiú, sonraí oibiachtúla a fháil agus breathnú ar na torthaí.

Ábhar staidéir

Tá roinnt bealaí ann chun uimhreacha randamacha a ghiniúint in Unity - rinneamar tástáil ar chúig cinn.

  1. Córas.Randamach.Ar Aghaidh(). Gineann sé slánuimhreacha i raon áirithe luachanna.
  2. Córas.Random.NextDouble(). Gineann beachta-uimhreacha dúbailte sa raon ó [0; 1).
  3. UnityEngine.Random.Range(). Gineann beachta-uimhreacha singil (snámháin) i raon áirithe luachanna.
  4. UnityEngine.Random.value. Gineann beachta-uimhreacha singil (snámháin) sa raon ó [0; 1).
  5. Aontacht.Matamaitic.Randamach.NextFloat(). Cuid de leabharlann nua Unity.Mathematics. Gineann beachta-uimhreacha singil (snámháin) i raon áirithe luachanna.

Beagnach i ngach áit sa doiciméadú sonraíodh dáileadh aonfhoirmeach, cé is moite de UnityEngine.Random.value (i gcás nár sonraíodh an dáileadh, ach de réir analaí le héide UnityEngine.Random.Range() bhíothas ag súil freisin) agus Unity.Mathematics.Random .NextFloat() (áit sa Is é an bunús an t-algartam xorshift, rud a chiallaíonn gur gá duit fanacht arís le dáileadh aonfhoirmeach).

De réir réamhshocraithe, glacadh leis na torthaí ionchais mar na cinn a shonraítear sa doiciméadú.

Teicníocht

Scríobhamar feidhmchlár beag a ghin seichimh uimhreacha randamacha ag baint úsáide as gach ceann de na modhanna a cuireadh i láthair agus a shábháil na torthaí le haghaidh tuilleadh próiseála.

Is é fad gach seicheamh ná 100 uimhir.
Is é raon na n-uimhreacha randamacha ná [0, 100).

Bailíodh sonraí ó roinnt ardán sprice:

  • Windows
    - Unity v2018.3.14f1, Modh Eagarthóra, Mona, .NET Standard 2.0
  • MacOS
    - Unity v2018.3.14f1, Modh Eagarthóra, Mona, .NET Standard 2.0
    — Unity v5.6.4p4, Modh Eagarthóra, Mona, .NET Standard 2.0
  • Android
    - Unity v2018.3.14f1, tógáil in aghaidh an fheiste, Mona, .NET Standard 2.0
  • iOS
    - Unity v2018.3.14f1, tógáil in aghaidh an fheiste, il2cpp, .NET Standard 2.0

Cur i bhFeidhm

Tá go leor bealaí éagsúla againn chun uimhreacha randamacha a ghiniúint. I gcás gach ceann acu, scríobhfaimid rang fillteáin ar leith, agus ba cheart go soláthródh sé:

  1. Deis an raon luachanna a shocrú [min/max). Socrófar é tríd an cruthaitheoir.
  2. Modh ag filleadh MF. A ligean ar a roghnú snámhphointe mar an cineál, mar go bhfuil sé níos ginearálta.
  3. Ainm an mhodha giniúna chun na torthaí a mharcáil. Ar mhaithe le caoithiúlacht, cuirfimid ar ais mar luach ainm iomlán an ranga + ainm an mhodha a úsáidtear chun an MF a ghiniúint.

Ar dtús, dearbhaimis astarraingt a léireoidh comhéadan IRandomGenerator:

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

        float Generate();
    }
}

Cur i bhfeidhm an Chórais.Random.Ar Aghaidh()

Ceadaíonn an modh seo duit raon luachanna a shocrú, ach filleann sé slánuimhreacha, ach tá gá le snámháin. Is féidir leat slánuimhir a léirmhíniú go simplí mar shnámhán, nó is féidir leat raon na luachanna a leathnú le roinnt orduithe méide, agus iad ag cúiteamh le gach glúin den mheánraon. Is é an toradh a bheidh air ná rud éigin cosúil le pointe seasta le hord cruinnis ar leith. Bainfimid úsáid as an rogha seo ós rud é go bhfuil sé níos gaire don fhíorluach snámhphointe.

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

Cur i bhfeidhm an Chórais.Random.NextDouble()

Anseo tá an raon seasta luachanna [0; 1). Chun é a theilgean ar an gceann atá sonraithe sa chruthaitheoir, úsáidimid uimhríocht shimplí: X * (uas - nóim) + 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;
    }
}

Cur i bhfeidhm UnityEngine.Random.Range()

Ceadaíonn an modh seo den rang statach UnityEngine.Random duit raon luachanna a shocrú agus cineál snámhphointe a chur ar ais. Ní gá duit aon chlaochlú breise a dhéanamh.

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

Cur i bhfeidhm ar luach UnityEngine.Random

Tugann maoin luach an ranga statach UnityEngine.Random cineál snámhphointe ar ais ó raon seasta luachanna [0; 1). Déanaimis é a theilgean ar raon áirithe ar an mbealach céanna agus a chuirtear i bhfeidhm 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;
    }
}

Cur i bhfeidhm Unity.Mathematics.Random.NextFloat()

Tugann modh NextFloat() den rang Unity.Mathematics.Random snámhphointe de chineál snámhphointe ar ais agus ligeann duit raon luachanna a shonrú. Is é an nuance amháin go mbeidh gach cás de Unity.Mathematics.Random a thúsú le roinnt síol - ar an mbealach seo beidh muid ag seachaint seichimh athrá a ghiniúint.

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

Feidhmiú an Phríomh-Rialtóra

Tá roinnt feidhmiúcháin de IRandomGenerator réidh. Ansin, ní mór duit seichimh a ghiniúint agus an tacar sonraí mar thoradh air a shábháil le haghaidh próiseála. Chun seo a dhéanamh, cruthóimid radharc agus script bheag MainController in Unity, a dhéanfaidh an obair riachtanach go léir agus ag an am céanna a bheidh freagrach as idirghníomhú leis an Chomhéadain.

Déanaimis méid an tacair sonraí agus raon na luachanna MF a shocrú, agus freisin modh a fháil a thugann ar ais raon gineadóirí atá cumraithe agus réidh le hobair.

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

        ...
    }
}

Anois cruthaimis tacar sonraí. Sa chás seo, déanfar giniúint sonraí a chomhcheangal leis na torthaí a thaifeadadh i sruth téacs (i bhformáid csv). Chun luachanna gach IRandomGenerator a stóráil, déantar a cholún ar leith féin a leithdháileadh, agus tá Ainm an ghineadóra sa chéad líne.

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

        ...
    }
}

Níl fágtha ach glaoch ar an modh GenerateCsvDataSet agus an toradh a shábháil i gcomhad, nó na sonraí a aistriú láithreach thar an líonra ón ngléas deiridh go dtí an freastalaí glactha.

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

        ...
    }
}

Tá foinsí an tionscadail ag GitLab.

Torthaí

Níor tharla míorúilt ar bith. Is é a raibh súil acu leis an méid a fuair siad - i ngach cás, dáileadh cothrom gan leid ar chomhcheilg. Ní fheicim an pointe maidir le graif ar leith a chur le haghaidh ardáin - léiríonn siad go léir thart ar na torthaí céanna.

Is é an réaltacht:
BlessRNG nó seiceáil an RNG le haghaidh cothroime

Amharcléiriú ar sheichimh ar eitleán ó gach ceann de na cúig mhodhanna giniúna:
BlessRNG nó seiceáil an RNG le haghaidh cothroime

Agus léirshamhlú i 3D. Ní fhágfaidh mé ach toradh System.Random.Next() ionas nach gcruthófar braon ábhar comhionann.
BlessRNG nó seiceáil an RNG le haghaidh cothroime

Ní dhearna an scéal a insíodh sa réamhrá faoi ghnáthdháileadh UnityEngine.Random é féin a athrá: bhí sé earráideach ar dtús, nó tá athrú tagtha ar rud éigin san inneall ó shin. Ach anois táimid cinnte.

Foinse: will.com

Add a comment