BlessRNG no thoir sùil air an RNG airson cothromachd

BlessRNG no thoir sùil air an RNG airson cothromachd

Ann an leasachadh geama, gu tric feumaidh tu rudeigin a cheangal suas le thuaiream: tha a Random fhèin aig Unity airson seo, agus ann an co-shìnte ris tha System.Random. Uair dhe na h-uairean, air aon de na pròiseactan, fhuair mi a’ bheachd gum faodadh an dithis obrachadh ann an dòigh eadar-dhealaichte (ged a bu chòir cuairteachadh cothromach a bhith aca).

An uairsin cha deach iad a-steach gu mion-fhiosrachadh - bha e gu leòr gun do cheartaich an gluasad gu System.Random na duilgheadasan gu lèir. A-nis chuir sinn romhainn sgrùdadh nas mionaidiche a dhèanamh air agus beagan rannsachaidh a dhèanamh: dè cho “claonach” no RNG a tha dùil, agus dè am fear a thaghas tu. A bharrachd air an sin, tha mi air barrachd air aon uair a chluinntinn beachdan connspaideach mun “onair” aca - feuchaidh sinn ri faighinn a-mach mar a tha na fìor thoraidhean an coimeas ris an fheadhainn a chaidh ainmeachadh.

Tha prògram foghlaim goirid no RNG gu dearbh na RNG

Ma tha thu eòlach mu thràth air gineadairean àireamhan air thuaiream, faodaidh tu leum gu dìreach chun roinn “Deuchainn”.

Tha àireamhan air thuaiream (RN) nan sreath de dh’ àireamhan air an gineadh a’ cleachdadh pròiseas air thuaiream (chaotic), stòr entropy. Is e sin, is e seo sreath nach eil na h-eileamaidean eadar-cheangailte le lagh matamataigeach sam bith - chan eil dàimh adhbhar-is-buaidh aca.

Canar gineadair àireamhan air thuaiream (RNG) ris an rud a chruthaicheas an àireamh air thuaiream. Bhiodh e coltach gu bheil a h-uile dad bunaiteach, ach ma ghluaiseas sinn bho theòiridh gu cleachdadh, gu dearbh chan eil e cho sìmplidh algorithm bathar-bog a chuir an gnìomh airson a leithid de shreath a ghineadh.

Is e an adhbhar nach eil an aon chaos ann an electronics luchd-cleachdaidh an latha an-diugh. Às aonais, sguir àireamhan air thuaiream a bhith air thuaiream, agus bidh an gineadair aca a’ tionndadh gu bhith na ghnìomh àbhaisteach de dh’ argamaidean a tha follaiseach. Airson grunn speisealaichean ann an raon IT, is e fìor dhuilgheadas a tha seo (mar eisimpleir, cryptography), ach dha feadhainn eile tha fuasgladh gu tur iomchaidh.

Feumar algorithm a sgrìobhadh a thilleadh, ged nach e àireamhan air thuaiream a bh’ annta, ach cho faisg ‘s a ghabhas dhaibh - na h-àireamhan meallta-air thuaiream (PRN). Canar gineadair àireamh pseudorandom (PRNG) ris an algairim sa chùis seo.

Tha grunn roghainnean ann airson PRNG a chruthachadh, ach bidh na leanas buntainneach don h-uile duine:

  1. Tha feum air tòiseachadh tòiseachaidh.

    Chan eil stòr entropy aig an PRNG, agus mar sin feumar ciad staid a thoirt dha mus tèid a chleachdadh. Tha e air a shònrachadh mar àireamh (no vectar) agus canar sìol (sìol air thuaiream). Gu tric, thathas a’ cleachdadh cuntair gleoc a’ phròiseasar no an àireamh co-ionann ri ùine an t-siostaim mar shìol.

  2. Ath-riochdachadh sreath.

    Tha am PRNG gu tur dearbhach, agus mar sin bidh an sìol a chaidh a shònrachadh aig àm tòiseachaidh a’ dearbhadh gu sònraichte an t-sreath àireamhan gu lèir san àm ri teachd. Tha seo a’ ciallachadh gun cruthaich PRNG air leth leis an aon sìol (aig amannan eadar-dhealaichte, ann am prògraman eadar-dhealaichte, air diofar innealan) an aon sreath.

Feumaidh tu cuideachd fios a bhith agad air an sgaoileadh coltachd a tha a’ comharrachadh an PRNG - dè na h-àireamhan a ghineas e agus dè an coltachd. Mar as trice is e cuairteachadh àbhaisteach no cuairteachadh èideadh a tha seo.
BlessRNG no thoir sùil air an RNG airson cothromachd
Sgaoileadh àbhaisteach (clì) agus cuairteachadh èideadh (deas)

Canaidh sinn gu bheil bàs cothromach againn le 24 taobhan. Ma thilgeas tu e, bidh an coltachd gum faigh thu fear co-ionann ri 1/24 (an aon rud ris a’ choltachd gum faigh thu àireamh sam bith eile). Ma nì thu mòran tilgeil agus gun clàraich thu na toraidhean, chì thu gu bheil na h-oirean uile a’ tuiteam a-mach leis an aon tricead. Gu bunaiteach, faodar am bàs seo a mheas mar RNG le cuairteachadh èideadh.

Dè ma thilgeas tu 10 de na dìsnean sin aig an aon àm agus gun cunnt thu na puingean iomlan? An tèid aonachdachd a chumail air a shon? Chan eil. Mar as trice, bidh an t-suim faisg air 125 puingean, is e sin, gu cuid de luach cuibheasach. Agus mar thoradh air an sin, eadhon mus dèan thu tilgeil, faodaidh tu tuairmse a dhèanamh air an toradh san àm ri teachd.

Is e an adhbhar gu bheil an àireamh as motha de choimeasgaidhean ann gus an sgòr cuibheasach fhaighinn. Mar as fhaide bhuaithe, is ann as lugha de choimeasgaidhean - agus, mar sin, nas ìsle an coltachd call. Ma thèid an dàta seo fhaicinn, bidh e gu math coltach ri cumadh clag. Mar sin, le beagan sìneadh, faodar siostam de 10 dìsnean ainmeachadh mar RNG le cuairteachadh àbhaisteach.

Eisimpleir eile, dìreach an turas seo air plèana - losgadh air targaid. Bidh an neach-seilg na RNG a ghineas paidhir àireamhan (x, y) a tha air a thaisbeanadh air a’ ghraf.
BlessRNG no thoir sùil air an RNG airson cothromachd
Aontaich gu bheil an roghainn air an taobh chlì nas fhaisge air fìor bheatha - is e seo RNG le cuairteachadh àbhaisteach. Ach ma dh'fheumas tu a bhith a 'sgapadh rionnagan ann an adhar dorcha, tha an roghainn cheart, a gheibhear le bhith a' cleachdadh RNG le cuairteachadh èideadh, nas freagarraiche. San fharsaingeachd, tagh gineadair a rèir na h-obrach a tha ri làimh.

A-nis bruidhnidh sinn mu entropy an t-sreath PNG. Mar eisimpleir, tha sreath ann a thòisicheas 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, ...

Dè cho iongantach sa tha na h-àireamhan sin aig a’ chiad sealladh? Feuch an tòisich sinn le bhith a 'sgrùdadh an t-sgaoilidh.
BlessRNG no thoir sùil air an RNG airson cothromachd
Tha e a’ coimhead faisg air èideadh, ach ma leughas tu sreath de dhà àireamh agus ma mhìnicheas tu iad mar cho-chomharran air plèana, gheibh thu seo:
BlessRNG no thoir sùil air an RNG airson cothromachd
Bidh pàtrain rim faicinn gu soilleir. Agus leis gu bheil an dàta san t-sreath air òrdachadh ann an dòigh shònraichte (is e sin, tha entropaidh ìosal aige), faodaidh seo an fhìor “chlaonadh” sin adhbhrachadh. Aig a’ char as lugha, chan eil leithid de PRNG gu math freagarrach airson co-chomharran a ghineadh air plèana.

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

Tha e coltach gu bheil a h-uile dad gu math an seo eadhon air an itealan:
BlessRNG no thoir sùil air an RNG airson cothromachd
Bheir sinn sùil ann an tomhas-lìonaidh (leugh trì àireamhan aig an aon àm):
BlessRNG no thoir sùil air an RNG airson cothromachd
Agus a-rithist na pàtranan. Chan eil e comasach tuilleadh sealladh a thogail ann an ceithir tomhasan. Ach faodaidh pàtrain a bhith ann air an taobh seo agus air feadhainn nas motha.

Ann an criptography, far a bheil na riatanasan as cruaidhe air an cur air PRNGn, tha suidheachadh mar sin gu tur neo-iomchaidh. Mar sin, chaidh algorithms sònraichte a leasachadh gus an càileachd a mheasadh, nach bi sinn a 'bruidhinn air a-nis. Tha an cuspair farsaing agus airidh air artaigil air leth.

Deuchainn

Mura h-eil fios againn gu cinnteach, ciamar a dh’ obraicheas sinn leis? Am b’ fhiach a dhol tarsainn air an rathad mura h-eil fios agad dè an solas trafaic a tha ga cheadachadh? Faodaidh na buaidhean a bhith eadar-dhealaichte.

Tha an aon rud a’ dol airson an iomraiteach air thuaiream ann an Unity. Tha e math ma tha na sgrìobhainnean a’ nochdadh am mion-fhiosrachadh riatanach, ach thachair an sgeulachd a chaidh ainmeachadh aig toiseach an artaigil dìreach air sgàth dìth mion-fhiosrachaidh a bha thu ag iarraidh.

Agus mura h-eil fios agad mar a tha an inneal ag obair, cha bhith e comasach dhut a chleachdadh gu ceart. San fharsaingeachd, tha an t-àm ann sgrùdadh a dhèanamh agus deuchainn a dhèanamh gus dèanamh cinnteach mu dheireadh co-dhiù mun sgaoileadh.

Bha am fuasgladh sìmplidh agus èifeachdach - cruinnich staitistig, faigh dàta amas agus coimhead air na toraidhean.

Cuspair an sgrùdaidh

Tha grunn dhòighean ann àireamhan air thuaiream a ghineadh ann an Unity - rinn sinn deuchainn air còig.

  1. System.Random.Next(). A’ gineadh iomlanachd ann an raon sònraichte de luachan.
  2. System.Random.NextDouble(). A’ gineadh àireamhan mionaideachd dùbailte anns an raon bho [0; 1).
  3. UnityEngine.Random.Range(). A’ gineadh àireamhan mionaideach singilte (floats) ann an raon luachan sònraichte.
  4. UnityEngine.Random.value. A’ gineadh àireamhan mionaideachd singilte (fleòdradh) anns an raon bho [0; 1).
  5. Unity.Mathematics.Random.NextFloat(). Mar phàirt den leabharlann ùr Unity.Mathematics. A’ gineadh àireamhan mionaideach singilte (floats) ann an raon luachan sònraichte.

Cha mhòr anns a h-uile àite anns na sgrìobhainnean chaidh cuairteachadh èideadh a shònrachadh, ach a-mhàin UnityEngine.Random.value (far nach robh an sgaoileadh air a shònrachadh, ach le co-chosmhail ri èideadh UnityEngine.Random.Range () bha dùil cuideachd) agus Unity.Mathematics.Random .NextFloat() (far a bheil an algairim xorshift anns a’ bhunait, a tha a’ ciallachadh gum feum thu a-rithist feitheamh airson cuairteachadh èideadh).

Gu gnàthach, chaidh na toraidhean ris an robh dùil a ghabhail mar an fheadhainn a chaidh a shònrachadh anns na sgrìobhainnean.

Modheòlas

Sgrìobh sinn tagradh beag a chruthaich sreathan de àireamhan air thuaiream a’ cleachdadh gach aon de na dòighean a chaidh a thaisbeanadh agus a shàbhail na toraidhean airson tuilleadh giollachd.

Is e fad gach sreath 100 àireamh.
Is e raon nan àireamhan air thuaiream [0, 100).

Chaidh dàta a chruinneachadh bho ghrunn àrd-ùrlaran targaid:

  • Windows
    - Aonachd v2018.3.14f1, modh deasaiche, Mono, .NET Standard 2.0
  • MacOS
    - Aonachd v2018.3.14f1, modh deasaiche, Mono, .NET Standard 2.0
    — Unity v5.6.4p4, Modh deasaiche, Mono, .NET Standard 2.0
  • Android
    - Unity v2018.3.14f1, togail gach inneal, Mono, .NET Standard 2.0
  • iOS
    - Unity v2018.3.14f1, togail gach inneal, il2cpp, .NET Standard 2.0

Реализация

Tha grunn dhòighean eadar-dhealaichte againn airson àireamhan air thuaiream a ghineadh. Airson gach fear dhiubh, sgrìobhaidh sinn clas fillte fa leth, a bu chòir a thoirt seachad:

  1. Comasach air an raon luachan a shuidheachadh [min / max). Thèid a shuidheachadh tron ​​​​neach-togail.
  2. Dòigh air ais MF. Feuch an tagh sinn fleòdradh mar an seòrsa, oir tha e nas fharsainge.
  3. Ainm an dòigh ginealach airson na toraidhean a chomharrachadh. Airson goireasachd, tillidh sinn mar luach ainm slàn a’ chlas + ainm an dòigh a chaidh a chleachdadh gus am MF a ghineadh.

An toiseach, leig dhuinn tarraing a-mach a bhios air a riochdachadh leis an eadar-aghaidh IRandomGenerator:

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

        float Generate();
    }
}

Cur an gnìomh an t-siostam.Random.Next()

Tha an dòigh seo a 'toirt cothrom dhut raon de luachan a shuidheachadh, ach bidh e a' tilleadh iomlanachd, ach tha feum air flotaichean. Faodaidh tu dìreach an t-sreath iomlan a mhìneachadh mar fleòdradh, no faodaidh tu an raon luachan a leudachadh le grunn òrdughan meudachd, gan dìoladh le gach ginealach den midrange. Bidh an toradh rudeigin mar phuing stèidhichte le òrdugh mionaideachd sònraichte. Cleachdaidh sinn an roghainn seo leis gu bheil e nas fhaisge air an fhìor luach fleòdraidh.

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 an gnìomh an t-siostam.Random.NextDouble()

Seo an raon stèidhichte de luachan [0; 1). Gus a chuir air an fhear a tha air a shònrachadh san neach-togail, bidh sinn a’ cleachdadh àireamhachd shìmplidh: 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;
    }
}

Cur an gnìomh UnityEngine.Random.Range()

Tha an dòigh seo den chlas statach UnityEngine.Random a 'toirt cothrom dhut raon luachan a shuidheachadh agus a' tilleadh seòrsa fleòdraidh. Chan fheum thu atharrachaidhean a bharrachd 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 an gnìomh luach UnityEngine.Random

Tha seilbh luach a 'chlas statach UnityEngine.Random a' tilleadh seòrsa fleòdraidh bho raon stèidhichte de luachan [0; 1). Feuch an cuir sinn a-steach e air raon sònraichte san aon dòigh ri nuair a chuirear an gnìomh 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 an gnìomh Unity.Mathematics.Random.NextFloat()

Bidh modh NextFloat() den chlas Unity.Mathematics.Random a’ tilleadh puing fleòdraidh de sheòrsa fleòdraidh agus a’ leigeil leat raon luachan a shònrachadh. Is e an aon rud a th 'ann gum feum gach eisimpleir de Unity.Mathematics.Random a bhith air a thòiseachadh le beagan sìol - mar seo bidh sinn a' seachnadh sreathan ath-aithris.

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

Cur an gnìomh a 'Phrìomh Rianadair

Tha grunn bhuileachadh de IRandomGenerator deiseil. An ath rud, feumaidh tu sreathan a ghineadh agus an dàta a thig às a shàbhaladh airson a ghiullachd. Gus seo a dhèanamh, cruthaichidh sinn sealladh agus sgriobt MainController beag ann an Unity, a nì a h-uile obair riatanach agus aig an aon àm a bhith cunntachail airson eadar-obrachadh leis an UI.

Suidhich sinn meud an t-seata dàta agus an raon de luachan MF, agus gheibh sinn cuideachd dòigh a thilleas sreath de ghineadairean air an rèiteachadh agus deiseil airson obrachadh.

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

        ...
    }
}

A-nis cruthaichidh sinn stòr-dàta. Anns a’ chùis seo, thèid gineadh dàta a chur còmhla ri bhith a’ clàradh nan toraidhean ann an sruth teacsa (ann an cruth csv). Gus luachan gach IRandomGenerator a stòradh, tha a cholbh fa leth fhèin air a riarachadh, agus tha Ainm a ’ghineadair anns a’ chiad loidhne.

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

        ...
    }
}

Chan eil air fhàgail ach an dòigh GenerateCsvDataSet a ghairm agus an toradh a shàbhaladh gu faidhle, no an dàta a ghluasad thairis air an lìonra sa bhad bhon inneal deireannach chun t-seirbheisiche faighinn.

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

        ...
    }
}

Tha stòran a’ phròiseict aig GitLab.

Toraidhean

Cha do thachair mìorbhail sam bith. Is e na bha iad a’ sùileachadh na fhuair iad - anns a h-uile cùis, cuairteachadh cothromach gun bheachd air co-fheall. Chan eil mi a’ faicinn a’ phuing ann a bhith a’ cur ghrafaichean fa-leth airson àrd-ùrlaran - tha iad uile a’ nochdadh timcheall air na h-aon toraidhean.

Is e an fhìrinn:
BlessRNG no thoir sùil air an RNG airson cothromachd

Amharc air sreathan air plèana bho na còig dòighean ginealach:
BlessRNG no thoir sùil air an RNG airson cothromachd

Agus lèirsinn ann an 3d. Chan fhàg mi ach toradh System.Random.Next() gus nach toir mi a-mach dòrlach de shusbaint co-ionann.
BlessRNG no thoir sùil air an RNG airson cothromachd

An sgeulachd a chaidh innse anns an ro-ràdh mu sgaoileadh àbhaisteach UnityEngine.Random cha do rinn e a-rithist e fhèin: an dàrna cuid bha e mearachdach an toiseach, no tha rudeigin air atharrachadh bhon uair sin san einnsean. Ach a-nis tha sinn cinnteach.

Source: www.habr.com

Cuir beachd ann