BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ

BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ

በጨዋታ እድገት ውስጥ ብዙውን ጊዜ አንድን ነገር በዘፈቀደ ማሰር ያስፈልግዎታል፡ አንድነት ለዚህ የራሱ የሆነ ራንደም አለው፣ እና ከእሱ ጋር በትይዩ ሲስተም.Random አለ። በአንድ ወቅት, በአንዱ ፕሮጀክቶች ላይ, ሁለቱም በተለየ መንገድ ሊሰሩ እንደሚችሉ (ምንም እንኳን እኩል ስርጭት ሊኖራቸው ይገባል) የሚል ስሜት አግኝቻለሁ.

ከዚያ ወደ ዝርዝሮች አልገቡም - ወደ ስርዓት መሸጋገሩ በቂ ነበር በዘፈቀደ ሁሉንም ችግሮች ያስተካክላል። አሁን የበለጠ በዝርዝር ለማየት እና ትንሽ ጥናት ለማካሄድ ወሰንን-“አድሏዊ” ወይም ሊገመቱ የሚችሉ RNGs እንዴት እንደሆኑ እና የትኛውን መምረጥ እንዳለብን ወስነናል። በተጨማሪም ፣ ስለ “ሐቀኝነታቸው” የሚጋጩ አስተያየቶችን ከአንድ ጊዜ በላይ ሰምቻለሁ - እውነተኛ ውጤቶቹ ከተገለጹት ጋር እንዴት እንደሚነፃፀሩ ለማወቅ እንሞክር ።

አጭር የትምህርት ፕሮግራም ወይም RNG በእውነቱ RNG ነው።

የዘፈቀደ ቁጥር ማመንጫዎችን ቀድሞውኑ የሚያውቁ ከሆነ ወዲያውኑ ወደ “ሙከራ” ክፍል መዝለል ይችላሉ።

የዘፈቀደ ቁጥሮች (RN) አንዳንድ የዘፈቀደ (የተመሰቃቀለ) ሂደትን፣ የኢንትሮፒ ምንጭን በመጠቀም የሚፈጠሩ የቁጥሮች ቅደም ተከተል ናቸው። ያም ማለት ይህ ቅደም ተከተል ነው የእሱ ክፍሎች በየትኛውም የሂሳብ ህግ ያልተገናኙ - መንስኤ እና ተፅእኖ ግንኙነት የላቸውም.

የዘፈቀደ ቁጥሩን የሚፈጥረው የዘፈቀደ ቁጥር ጀነሬተር (RNG) ይባላል። ሁሉም ነገር የመጀመሪያ ደረጃ ይመስላል ፣ ግን ከንድፈ-ሀሳብ ወደ ልምምድ ከተንቀሳቀስን ፣ በእውነቱ እንደዚህ አይነት ቅደም ተከተል ለመፍጠር የሶፍትዌር ስልተ ቀመር መተግበር በጣም ቀላል አይደለም።

ምክንያቱ በዘመናዊ የፍጆታ ኤሌክትሮኒክስ ውስጥ ተመሳሳይ ትርምስ ባለመኖሩ ነው። ያለሱ፣ የዘፈቀደ ቁጥሮች በዘፈቀደ መሆናቸው ያቆማሉ፣ እና ጀነሬተራቸው ወደ ተራ ተግባር ወደ ግልጽ የተገለጹ ክርክሮች ይቀየራል። በ IT መስክ ውስጥ ላሉት ልዩ ባለሙያዎች ይህ ከባድ ችግር ነው (ለምሳሌ ፣ ምስጠራ) ፣ ግን ለሌሎች ሙሉ በሙሉ ተቀባይነት ያለው መፍትሄ አለ።

ምንም እንኳን በእውነት የዘፈቀደ ቁጥሮች ባይሆኑም ፣ ግን በተቻለ መጠን ለእነሱ ቅርብ - የውሸት-ራንደም ቁጥሮች (PRN) የሚባሉት ፣ የሚመለስ ስልተ ቀመር መጻፍ አስፈላጊ ነው። በዚህ ጉዳይ ላይ ያለው ስልተ ቀመር pseudorandom ቁጥር ጄኔሬተር (PRNG) ይባላል።

PRNG ለመፍጠር ብዙ አማራጮች አሉ ነገር ግን የሚከተለው ለሁሉም ሰው ጠቃሚ ይሆናል፡

  1. የቅድሚያ ጅምር አስፈላጊነት.

    PRNG የኢንትሮፒ ምንጭ የለውም፣ ስለዚህ ከመጠቀምዎ በፊት የመጀመሪያ ሁኔታ መሰጠት አለበት። እሱ እንደ ቁጥር (ወይም ቬክተር) የተገለጸ ሲሆን ዘር (የዘፈቀደ ዘር) ይባላል። ብዙውን ጊዜ የማቀነባበሪያው ሰዓት ቆጣሪ ወይም የስርዓት ጊዜ አሃዛዊ አሃዝ እንደ ዘር ጥቅም ላይ ይውላል።

  2. ቅደም ተከተል እንደገና መራባት.

    PRNG ሙሉ በሙሉ የሚወስን ነው፣ ስለዚህ በጅማሬ ወቅት የተገለፀው ዘር የወደፊቱን የቁጥሮች ቅደም ተከተል በልዩ ሁኔታ ይወስናል። ይህ ማለት በተመሳሳዩ ዘር (በተለያዩ ጊዜዎች ፣ በተለያዩ ፕሮግራሞች ፣ በተለያዩ መሳሪያዎች) የተጀመረ የተለየ PRNG ተመሳሳይ ቅደም ተከተል ይፈጥራል።

እንዲሁም የ PRNG ባህሪን የሚገልጽ የፕሮባቢሊቲ ስርጭት ማወቅ አለቦት - ምን ቁጥሮች እንደሚያመነጭ እና ከየትኛው ዕድል ጋር። ብዙውን ጊዜ ይህ መደበኛ ስርጭት ወይም ወጥ የሆነ ስርጭት ነው።
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
መደበኛ ስርጭት (ግራ) እና ወጥ ስርጭት (በስተቀኝ)

24 ወገን ያለው ፍትሃዊ ሞት አለን እንበል። ከወረወሩት አንድ የማግኘት እድሉ ከ1/24 ጋር እኩል ይሆናል (ሌላ ቁጥር የማግኘት እድሉ ተመሳሳይ ነው)። ብዙ ውርወራዎችን ካደረጉ እና ውጤቱን ከመዘገቡ, ሁሉም ጠርዞች በግምት ተመሳሳይ ድግግሞሽ እንደሚወድቁ ያስተውላሉ. በመሰረቱ፣ ይህ ዳይ ወጥ የሆነ ስርጭት ያለው RNG ተደርጎ ሊወሰድ ይችላል።

ከእነዚህ ውስጥ 10 ቱን በአንድ ጊዜ ብትጥል እና አጠቃላይ ነጥቦቹን ብትቆጥርስ? ለእሱ ተመሳሳይነት ይጠበቅ ይሆን? አይ. ብዙውን ጊዜ, መጠኑ ወደ 125 ነጥቦች, ማለትም ለአንዳንድ አማካኝ እሴት ቅርብ ይሆናል. እና በውጤቱም, ከመወርወርዎ በፊት እንኳን, የወደፊቱን ውጤት በግምት መገመት ይችላሉ.

ምክንያቱ አማካይ ነጥብ ለማግኘት ከፍተኛው የጥምረቶች ብዛት በመኖሩ ነው። ከእሱ የራቀ, ጥቂቶቹ ጥምሮች - እና, በዚህ መሠረት, የመጥፋት እድሉ ዝቅተኛ ነው. ይህ መረጃ በምስላዊ መልኩ ከታየ፣ በድብቅ የደወል ቅርጽን ይመስላል። ስለዚህ, በተወሰነ ደረጃ, የ 10 ዳይስ ስርዓት መደበኛ ስርጭት ያለው RNG ተብሎ ሊጠራ ይችላል.

ሌላ ምሳሌ, በዚህ ጊዜ ብቻ በአውሮፕላን ላይ - ዒላማ ላይ መተኮስ. ተኳሹ በግራፉ ላይ የሚታዩ ጥንድ ቁጥሮችን (x, y) የሚያመነጭ RNG ይሆናል.
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
በግራ በኩል ያለው አማራጭ ወደ እውነተኛው ህይወት ቅርብ እንደሆነ ይስማሙ - ይህ የተለመደ ስርጭት ያለው RNG ነው. ግን በጨለማ ሰማይ ውስጥ ኮከቦችን መበተን ካስፈለገዎት RNG ን ከአንድ ወጥ ስርጭት ጋር በመጠቀም የተገኘው ትክክለኛው አማራጭ የተሻለ ነው። በአጠቃላይ በእጃቸው ባለው ተግባር ላይ በመመስረት ጀነሬተር ይምረጡ.

አሁን ስለ PNG ቅደም ተከተል ስለ ኢንትሮፒ እንነጋገር. ለምሳሌ፣ እንደሚከተለው የሚጀምር ቅደም ተከተል አለ።

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

በመጀመሪያ እይታ እነዚህ ቁጥሮች ምን ያህል በዘፈቀደ ናቸው? ስርጭቱን በማጣራት እንጀምር።
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
ወደ ዩኒፎርም ቅርብ ይመስላል ነገር ግን የሁለት ቁጥሮችን ቅደም ተከተል ካነበቡ እና በአውሮፕላን ላይ እንደ መጋጠሚያዎች ከተረጎሟቸው የሚከተለውን ያገኛሉ፡-
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
ቅጦች በግልጽ ይታያሉ. እና በቅደም ተከተል ውስጥ ያለው መረጃ በተወሰነ መንገድ የታዘዘ ስለሆነ (ይህም ዝቅተኛ ኢንትሮፒየም አለው) ይህ ለዚያ በጣም "አድሎአዊነት" ሊፈጥር ይችላል. ቢያንስ, እንዲህ ዓይነቱ PRNG በአውሮፕላን ላይ መጋጠሚያዎችን ለመፍጠር በጣም ተስማሚ አይደለም.

ሌላ ቅደም ተከተል:

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

በአውሮፕላኑ ውስጥ እንኳን ሁሉም ነገር ጥሩ ይመስላል።
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
በድምፅ እንመልከተው (በአንድ ጊዜ ሶስት ቁጥሮችን ያንብቡ)፡-
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ
እና እንደገና ቅጦች. ከአሁን በኋላ በአራት ልኬቶች ውስጥ ምስላዊነትን መገንባት አይቻልም. ነገር ግን ቅጦች በዚህ ልኬት እና በትላልቅ ሰዎች ላይ ሊኖሩ ይችላሉ.

በ PRNGs ላይ በጣም ጥብቅ የሆኑ መስፈርቶች በሚተገበሩበት ክሪፕቶግራፊ ውስጥ, እንዲህ ዓይነቱ ሁኔታ ፈጽሞ ተቀባይነት የለውም. ስለዚህ, ጥራታቸውን ለመገምገም ልዩ ስልተ ቀመሮች ተዘጋጅተዋል, አሁን አንነካውም. ርዕሱ ሰፊ ነው እና የተለየ ጽሑፍ ይገባዋል።

ሙከራ

አንድ ነገር በእርግጠኝነት ካላወቅን ታዲያ እንዴት ከእሱ ጋር መስራት እንደሚቻል? የትኛው የትራፊክ መብራት እንደሚፈቅድ ካላወቁ መንገዱን መሻገር ጠቃሚ ነው? የሚያስከትለው መዘዝ የተለየ ሊሆን ይችላል።

በዩኒቲ ውስጥ ላለው ታዋቂው የዘፈቀደ ሁኔታም ተመሳሳይ ነው። ሰነዱ አስፈላጊ የሆኑትን ዝርዝሮች ካሳየ ጥሩ ነው, ነገር ግን በአንቀጹ መጀመሪያ ላይ የተጠቀሰው ታሪክ የተፈለገውን ዝርዝር እጥረት ባለበት በትክክል ተከስቷል.

እና መሳሪያው እንዴት እንደሚሰራ ካላወቁ በትክክል መጠቀም አይችሉም. በአጠቃላይ ቢያንስ ስለ ስርጭቱ ቢያንስ በመጨረሻ ለማረጋገጥ ሙከራን ለመፈተሽ እና ለማካሄድ ጊዜው ደርሷል።

መፍትሄው ቀላል እና ውጤታማ ነበር - ስታቲስቲክስን ይሰብስቡ, ተጨባጭ መረጃ ያግኙ እና ውጤቱን ይመልከቱ.

የጥናት ርዕሰ ጉዳይ

በዩኒቲ ውስጥ የዘፈቀደ ቁጥሮችን ለመፍጠር ብዙ መንገዶች አሉ - አምስትን ሞከርን።

  1. ስርዓት. የዘፈቀደ.ቀጣይ()። በተወሰነ የእሴቶች ክልል ውስጥ ኢንቲጀሮችን ያመነጫል።
  2. ስርዓት.Random.NextDouble() ከ [0] ባለው ክልል ውስጥ ድርብ ትክክለኛነት ቁጥሮችን ያመነጫል። 1)
  3. UnityEngine.Random.Range() በተወሰነ የእሴቶች ክልል ውስጥ ነጠላ ትክክለኛ ቁጥሮችን (ተንሳፋፊዎችን) ያመነጫል።
  4. UnityEngine.Random.value. ከ [0] ባለው ክልል ውስጥ ነጠላ ትክክለኛ ቁጥሮችን (ተንሳፋፊዎችን) ያመነጫል። 1)
  5. አንድነት.ማቲማቲክስ.ራንደም.ቀጣይ ፍሎት()። የአዲሱ አንድነት.ማቲማቲክስ ቤተ-መጽሐፍት አካል። በተወሰነ የእሴቶች ክልል ውስጥ ነጠላ ትክክለኛ ቁጥሮችን (ተንሳፋፊዎችን) ያመነጫል።

በሰነዱ ውስጥ በሁሉም ቦታ ማለት ይቻላል አንድ ወጥ ስርጭት ተለይቷል፣ ከUnityEngine.Random.value በስተቀር (ስርጭቱ ያልተገለጸበት፣ ነገር ግን በ UnityEngine.Random.Range() ዩኒፎርም ተመሳሳይነት ይጠበቃል) እና Unity.Mathematics.Random .NextFloat () (በመሠረቱ የ xorshift አልጎሪዝም ነው ፣ ይህ ማለት እንደገና አንድ ወጥ ስርጭት መጠበቅ አለብዎት)።

በነባሪ, የሚጠበቀው ውጤት በሰነዱ ውስጥ እንደተገለፀው ተወስዷል.

ዘዴ

እያንዳንዱን የቀረቡትን ዘዴዎች በመጠቀም የዘፈቀደ ቁጥሮች ቅደም ተከተሎችን የፈጠረ ትንሽ መተግበሪያ ጻፍን እና ውጤቱን ለቀጣይ ሂደት አስቀምጠናል።

የእያንዳንዱ ቅደም ተከተል ርዝመት 100 ቁጥሮች ነው.
የዘፈቀደ ቁጥሮች ክልል [0, 100) ነው።

መረጃ ከተለያዩ የዒላማ መድረኮች ተሰብስቧል፡-

  • የ Windows
    — አንድነት v2018.3.14f1፣ የአርታዒ ሁኔታ፣ ሞኖ፣ .NET መደበኛ 2.0
  • macOS
    — አንድነት v2018.3.14f1፣ የአርታዒ ሁኔታ፣ ሞኖ፣ .NET መደበኛ 2.0
    - አንድነት v5.6.4p4, የአርታዒ ሁነታ, ሞኖ, .NET መደበኛ 2.0
  • የ Android
    — አንድነት v2018.3.14f1፣ በአንድ መሣሪያ ገንባ፣ ሞኖ፣ .NET መደበኛ 2.0
  • የ iOS
    — አንድነት v2018.3.14f1፣ በየመሣሪያ ገንባ፣ il2cpp፣ .NET Standard 2.0

ትግበራ

የዘፈቀደ ቁጥሮችን ለመፍጠር የተለያዩ መንገዶች አሉን። ለእያንዳንዳቸው የተለየ የመጠቅለያ ክፍል እንጽፋለን ፣ እሱም የሚከተሉትን ማቅረብ አለበት-

  1. የእሴቶችን ክልል የማዘጋጀት ዕድል [ደቂቃ/ከፍተኛ)። በገንቢው በኩል ይዘጋጃል።
  2. MF የመመለስ ዘዴ. ተንሳፋፊን እንደ አይነቱ እንምረጥ፣ እሱ የበለጠ አጠቃላይ ነው።
  3. ውጤቶቹን ለማመልከት የትውልድ ዘዴ ስም. ለመመቻቸት እንደ እሴት የክፍሉን ሙሉ ስም + ኤምኤፍ ለማመንጨት ጥቅም ላይ የዋለውን ዘዴ ስም እንመልሳለን.

በመጀመሪያ፣ በIRandomGenerator በይነገጽ የሚወከለውን ረቂቅ እናውጅ፡-

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

        float Generate();
    }
}

የስርዓት ትግበራ. የዘፈቀደ.ቀጣይ()

ይህ ዘዴ የተለያዩ እሴቶችን እንዲያዘጋጁ ያስችልዎታል, ነገር ግን ኢንቲጀሮችን ይመልሳል, ነገር ግን ተንሳፋፊዎች ያስፈልጋሉ. ኢንቲጀርን እንደ ተንሳፋፊ በቀላሉ መተርጎም ይችላሉ ፣ ወይም የእሴቶቹን ወሰን በበርካታ ትላልቅ ትዕዛዞች ማስፋፋት ፣ በእያንዳንዱ መካከለኛ ትውልድ ማካካስ ይችላሉ። ውጤቱም ከትክክለኛው ቅደም ተከተል ጋር እንደ ቋሚ ነጥብ ያለ ነገር ይሆናል. ከእውነተኛው ተንሳፋፊ እሴት ጋር ስለሚቀራረብ ይህን አማራጭ እንጠቀማለን.

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

የስርዓት ትግበራ.Random.ቀጣይ ድርብ()

እዚህ ቋሚ የእሴቶች ክልል [0; 1) በግንባታው ውስጥ በተጠቀሰው ላይ ለመንደፍ ቀላል አርቲሜቲክን እንጠቀማለን-X * (ከፍተኛ - ደቂቃ) + ደቂቃ።

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

የአንድነት ኢንጂን ትግበራ.Random.Range()

ይህ የUnityEngine.Random static class ዘዴ የተለያዩ እሴቶችን እንዲያዘጋጁ እና የተንሳፋፊ አይነትን ይመልሳል። ምንም ተጨማሪ ለውጦችን ማድረግ የለብዎትም.

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

UnityEngine.Random.value ትግበራ

የማይንቀሳቀስ ክፍል UnityEngine.Random እሴት ከቋሚ የእሴቶች ክልል ውስጥ ተንሳፋፊ አይነት ይመልሳል [0; 1) 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;
    }
}

የአንድነት.ማቲማቲክስ.ነሲብ.ቀጣይ ፍሎት() ትግበራ

የNextFloat() የUniity.Mathematics.Random class ዘዴ ተንሳፋፊ አይነት ተንሳፋፊ ነጥብ ይመልሳል እና የእሴቶችን ክልል እንዲገልጹ ያስችልዎታል። ብቸኛው ልዩነት እያንዳንዱ የUniity.Mathematics.Random ምሳሌ በአንዳንድ ዘር መጀመር አለበት - በዚህ መንገድ ተደጋጋሚ ቅደም ተከተሎችን መፍጠር እንቆጠባለን።

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

የ MainController ትግበራ

በርካታ የIRandomGenerator ትግበራዎች ዝግጁ ናቸው። በመቀጠል, ቅደም ተከተሎችን ማፍለቅ እና የተገኘውን የውሂብ ስብስብ ለማስኬድ ማስቀመጥ ያስፈልግዎታል. ይህንን ለማድረግ በዩኒቲ ውስጥ ትእይንት እና ትንሽ የ MainController ስክሪፕት እንፈጥራለን ፣ ይህም ሁሉንም አስፈላጊ ስራዎችን እና በተመሳሳይ ጊዜ ከዩአይዩ ጋር መስተጋብር ኃላፊነት አለበት።

የመረጃ ቋቱን መጠን እና የኤምኤፍ እሴቶችን መጠን እናስቀምጥ፣ እና እንዲሁም የተዋቀሩ እና ለመስራት ዝግጁ የሆኑ ጄነሬተሮችን የሚመልስ ዘዴን እናገኝ።

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

        ...
    }
}

አሁን የውሂብ ስብስብ እንፍጠር. በዚህ አጋጣሚ የውሂብ ማመንጨት ውጤቱን ወደ ጽሑፍ ዥረት (በ csv ቅርጸት) ከመመዝገብ ጋር ይጣመራል. የእያንዳንዱን IRandomGenerator እሴቶችን ለማከማቸት የራሱ የተለየ አምድ ተመድቧል ፣ እና የመጀመሪያው መስመር የጄነሬተሩን ስም ይይዛል።

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

        ...
    }
}

የቀረው የ GenerateCsvDataSet ዘዴን በመጥራት ውጤቱን ወደ ፋይል ማስቀመጥ ወይም ወዲያውኑ በአውታረ መረቡ ላይ ያለውን መረጃ ከመጨረሻው መሣሪያ ወደ ተቀባዩ አገልጋይ ማስተላለፍ ብቻ ነው።

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

        ...
    }
}

የፕሮጀክቱ ምንጮች በ GitLab.

ውጤቶች

ምንም ተአምር አልተፈጠረም። እነሱ የጠበቁት ያገኙትን ነው - በሁሉም ሁኔታዎች ፣ የሴራ ፍንጭ የሌለበት እኩል ስርጭት። ለመድረኮች የተለየ ግራፎችን ማስቀመጥ ነጥቡ አይታየኝም - ሁሉም በግምት ተመሳሳይ ውጤቶችን ያሳያሉ።

እውነታው ይህ ነው።
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ

ከአምስት ትውልድ ዘዴዎች በአውሮፕላን ላይ ቅደም ተከተሎችን ማየት-
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ

እና ምስላዊነት በ3-ል. ተመሳሳይ ይዘት ላለማድረግ የSystem.Random.Next()ን ውጤት ብቻ እተወዋለሁ።
BlessRNG ወይም RNG ለፍትሃዊነት ያረጋግጡ

በመግቢያው ላይ ስለ UnityEngine መደበኛ ስርጭት የተነገረው ታሪክ.Random እራሱን አልደገመም: ወይም መጀመሪያ ላይ ስህተት ነበር, ወይም ከዚያ በኋላ የሆነ ነገር በሞተሩ ውስጥ ተለውጧል. አሁን ግን እርግጠኛ ነን።

ምንጭ: hab.com

አስተያየት ያክሉ