
د لوبې په پراختیا کې، تاسو ډیری وخت په تصادفي تکیه کولو ته اړتیا لرئ: یووالي د دې لپاره خپل تصادفي لري، او سیسټم. تصادفي د هغې تر څنګ شتون لري. ډیر وخت دمخه، په یوه پروژه کې، ما دا تاثر ترلاسه کړ چې دواړه ممکن په مختلف ډول کار وکړي (که څه هم دوی باید یو شان ویش ولري).
موږ هغه وخت په تفصیل کې نه وو تللي - دا کافي وه چې سیسټم. رینډم ته بدلول ټولې ستونزې حل کړې. اوس موږ پریکړه کړې چې نږدې وګورو او یوه کوچنۍ مطالعه ترسره کړو: RNGs څومره "متعصب" یا د وړاندوینې وړ دي، او کوم یو غوره کړو. سربیره پردې، ما د دوی "انصاف" په اړه متضاد نظرونه له یو ځل څخه ډیر اوریدلي دي - راځئ چې هڅه وکړو چې معلومه کړو چې اصلي پایلې د ادعاوو سره څنګه پرتله کوي.
د RNG لنډه پېژندنه یا دا واقعیا RNG ده؟
که تاسو دمخه د تصادفي شمیرې جنراتورونو سره بلد یاست، تاسو کولی شئ د "ازموینې" برخې ته لاړ شئ.
ناڅاپي شمېرې (RN) د شمېرو یوه لړۍ ده چې د یو څه ناڅاپي (ګډوډ) پروسې لخوا رامینځته کیږي، د انټروپي سرچینه. دا، دا یوه لړۍ ده چې عناصر یې د کوم ریاضيکي قانون له مخې یو بل سره تړاو نلري - دوی د علت او اغیز اړیکه نلري.
هغه څه چې د تصادفي شمېرې جنراتور (RNG) جوړوي د تصادفي شمېرې جنراتور (RNG) په نوم یادیږي. پداسې حال کې چې دا ساده ښکاري، د تیوري عملي کول ښیي چې د داسې ترتیب د رامینځته کولو لپاره د سافټویر الګوریتم پلي کول دومره ساده ندي.
دلیل یې په عصري مصرف کونکي الیکترونیکونو کې د دې خورا ناڅاپي نشتوالي کې دی. پرته له دې، تصادفي شمیرې تصادفي پاتې کیږي، او د دوی جنراتور د مخکې ټاکل شوي ان پټونو په ساده فعالیت بدلیږي. د یو شمیر معلوماتي ټکنالوژۍ مسلکونو لپاره (د مثال په توګه، کریپټوګرافي)، دا یوه جدي ستونزه ده، مګر د نورو لپاره، یو بشپړ د منلو وړ حل شتون لري.
موږ باید یو داسې الګوریتم ولیکو چې هغه شمیرې بیرته راولي چې په ریښتیا سره ناڅاپي نه وي، مګر د امکان تر حده ورته نږدې وي - د جعلي ناڅاپي شمیرې (PRNGs) په نوم یادیږي. پدې حالت کې الګوریتم د جعلي ناڅاپي شمیرې جنریټر (PRNG) په نوم یادیږي.
د PRNG جوړولو لپاره ډیری انتخابونه شتون لري، مګر لاندې به د ټولو لپاره اړونده وي:
- د مخکې پیل کولو اړتیا.
PRNG د انټروپي سرچینه نلري، نو د کارولو دمخه باید یو ابتدايي حالت مشخص شي. دا ابتدايي حالت د شمیرې (یا ویکتور) په توګه مشخص شوی او د تخم (تصادفي تخم) په نوم یادیږي. د پروسسر دورې کاونټر یا د سیسټم وخت عددي معادل ډیری وختونه د تخم په توګه کارول کیږي.
- د تسلسل د تکثیر وړتیا.
PRNG په بشپړه توګه ټاکونکی دی، نو هغه تخم چې د پیل کولو پرمهال مشخص شوی په ځانګړي ډول د شمیرو ټول راتلونکی ترتیب ټاکي. دا پدې مانا ده چې یو واحد PRNG چې د ورته تخم سره پیل شوی (په مختلفو وختونو کې، په مختلفو پروګرامونو کې، په مختلفو وسیلو کې) به ورته ترتیب رامینځته کړي.
تاسو باید د احتمالي ویش په اړه هم پوه شئ چې PRNG ځانګړتیاوي لري - کوم شمیرې به تولید کړي او د کوم احتمال سره. ډیری وختونه، دا یا یو عادي ویش یا یو یونیفورم ویش دی.

عادي ویش (کیڼ اړخ ته) او یونیفورم ویش (ښي اړخ ته)
فرض کړئ چې موږ یو مناسب ۲۴ اړخیزه ډای لرو. که موږ دا رول کړو، نو په ۱ باندې د کښیناستلو احتمال ۱/۲۴ دی (لکه څنګه چې په کوم بل شمیر باندې د کښیناستلو احتمال). که موږ ډیری رولونه جوړ کړو او پایلې ثبت کړو، نو موږ به وګورو چې ټول ۲۴ اړخیزه ډای تقریبا ورته فریکونسۍ سره ځمکه کوي. په اصل کې، دا ډای د یو شان ویشل شوي تصادفي شمیرې جنراتور په توګه ګڼل کیدی شي.
که تاسو په یو وخت کې داسې ۱۰ ډایسونه وغورځوئ او ټول نمره محاسبه کړئ نو څه به وي؟ ایا دا به یو شان پاتې شي؟ نه. ډیری وختونه، نمره به د ۱۲۵ ټکو سره نږدې وي، دا یو څه اوسط ارزښت دی. د پایلې په توګه، تاسو کولی شئ د راتلونکي پایلې اټکل حتی مخکې له دې چې تاسو رول وکړئ.
دلیل یې دا دی چې د اوسط نمره ته د رسیدو لپاره د ترکیبونو ترټولو لوی شمیر شتون لري. هرڅومره چې له اوسط څخه لرې وي، هغومره لږ ترکیبونه شتون لري - او په پایله کې، د رول احتمال ټیټ وي. که دا معلومات لیدل شوي وای، نو دوی به په مبهم ډول د زنګ شکل ته ورته وای. له همدې امله، د یو څه غځولو سره، د 10 ډایسونو سیسټم په نورمال ډول ویشل شوی RNG بلل کیدی شي.
بله بیلګه، دا ځل په الوتکه کې، په هدف ډزې کول دي. ډزې کوونکی یو تصادفي شمیر جنراتور (RNG) دی، کوم چې د شمیرو یوه جوړه (x، y) تولیدوي، کوم چې په ګراف کې ښودل کیږي.

تاسو به موافق یاست چې د چپ لاس ډول حقیقي ژوند ته نږدې دی - دا د عادي ویش سره یو ناڅاپي شمیر جنراتور دی. مګر که تاسو اړتیا لرئ چې ستوري په تیاره اسمان کې وویشئ، د ښي لاس ډول، چې د یوشان ویشل شوي ناڅاپي شمیر جنراتور په کارولو سره ترلاسه کیږي، ډیر مناسب وي. په لنډه توګه، د لاس په کار کې د دندې پراساس یو جنراتور غوره کړئ.
اوس راځئ چې د ناڅاپي شمېرو د ترتیب د انټروپي په اړه وغږیږو. د مثال په توګه، یو ترتیب شتون لري چې په دې ډول پیل کیږي:
۸۹، ۹۳، ۳۳، ۳۲، ۸۲، ۲۱، ۴، ۴۲، ۱۱، ۸، ۶۰، ۹۵، ۵۳، ۳۰، ۴۲، ۱۹، ۳۴، ۳۵، ۶۲، ۲۳، ۴۴، ۳۸، ۷۴، ۳۶، ۵۲، ۱۸، ۵۸، ۷۹، ۶۵، ۴۵، ۹۹، ۹۰، ۸۲، ۲۰، ۴۱، ۱۳، ۸۸، ۷۶، ۸۲، ۲۴، ۵، ۵۴، ۷۲، ۱۹، ۸۰، ۲، ۷۴، ۳۶، ۷۱، ۹، …
دا شمېرې په لومړي نظر کې څومره ناڅاپي دي؟ راځئ چې د ویش په چک کولو سره پیل وکړو.

دا نږدې یونیفورم ښکاري، مګر که تاسو د دوو شمېرو ترتیب ولولئ او په یوه الوتکه کې یې د همغږۍ په توګه تشریح کړئ، نو تاسو دا ترلاسه کوئ:

نمونې په څرګنده توګه لیدل کیږي. او څرنګه چې په ترتیب کې معلومات په یو ځانګړي ډول ترتیب شوي (یعنې، ټیټ انټروپي لري)، دا کولی شي ورته "تعصب" رامینځته کړي. لږترلږه، دا ډول PRNG په الوتکه کې د همغږۍ تولید لپاره خورا مناسب نه دی.
بله لړۍ:
۸۹، ۹۳، ۳۳، ۳۲، ۸۲، ۲۱، ۴، ۴۲، ۱۱، ۸، ۶۰، ۹۵، ۵۳، ۳۰، ۴۲، ۱۹، ۳۴، ۳۵، ۶۲، ۲۳، ۴۴، ۳۸، ۷۴، ۳۶، ۵۲، ۱۸، ۵۸، ۷۹، ۶۵، ۴۵، ۹۹، ۹۰، ۸۲، ۲۰، ۴۱، ۱۳، ۸۸، ۷۶، ۸۲، ۲۴، ۵، ۵۴، ۷۲، ۱۹، ۸۰، ۲، ۷۴، ۳۶، ۷۱، ۹، …
داسې ښکاري چې دلته هرڅه سم دي، حتی په فلیټ سطحه کې:

راځئ چې حجم وګورو (درې شمېرې ولولئ):

او بیا، نمونې. په څلورو ابعادو کې لیدل نور ممکن نه دي. مګر نمونې په دې ابعادو او لوړو ابعادو کې شتون لري.
په کریپټوګرافي کې، چیرې چې په PRNGs باندې خورا سخت اړتیاوې وضع کیږي، دا ډول وضعیت په بشپړ ډول د منلو وړ نه دی. له همدې امله، د دوی کیفیت ارزولو لپاره ځانګړي الګوریتمونه رامینځته شوي، چې موږ به یې دلته بحث ونه کړو. موضوع پراخه ده او د جلا مقالې اړتیا لري.
ازمايښت
که موږ په ډاډمن ډول یو څه نه پوهیږو، نو څنګه ورسره معامله کولی شو؟ ایا موږ باید له سړک څخه تیر شو که موږ نه پوهیږو چې کوم ترافیکي څراغ اجازه ورکوي؟ پایلې یې توپیر کولی شي.
په یونیټي کې د بدنام تصادفي لپاره هم همداسې ده. دا ډیره ښه ده کله چې اسناد اړین توضیحات وړاندې کوي، مګر هغه پیښه چې د مقالې په پیل کې ذکر شوې وه په سمه توګه د مطلوب مشخصیت نشتوالي له امله رامینځته شوه.
او پرته له دې چې پوه شئ چې دا وسیله څنګه کار کوي، تاسو نشئ کولی دا په سمه توګه وکاروئ. نو، دا وخت دی چې دا ازموینه وکړئ او تجربه ترسره کړئ ترڅو بالاخره ډاډ ترلاسه کړئ، لږترلږه د ویش په اړه.
حل لاره ساده او مؤثره وه: احصایې راټولې کړئ، عیني معلومات ترلاسه کړئ، او پایلو ته وګورئ.
د څېړنې موضوع
په یونیټي کې د تصادفي شمېرو د تولید لپاره څو لارې شتون لري — موږ پنځه یې ازموینه وکړه.
- System.Random.Next(). د ارزښتونو په ټاکل شوي حد کې عددونه تولیدوي.
- System.Random.NextDouble(). د [0; 1) په حد کې دوه ګونی دقیق شمیرې رامینځته کوي.
- UnityEngine.Random.Range(). د ارزښتونو په ټاکل شوي حد کې د واحد دقیق شمیرې (تیریږي) تولیدوي.
- UnityEngine.Random.value. د [0; 1] په حد کې واحد-دقیق شمیرې (float) تولیدوي.
- Unity.Mathematics.Random.NextFloat(). د نوي Unity.Mathematics کتابتون برخه. په یوه ټاکل شوي حد کې د واحد دقیق فلوټ شمیرې تولیدوي.
په اسنادو کې تقریبا هر ځای، یو یونیفورم ویش مشخص شوی و، پرته له UnityEngine.Random.value (چیرې چې ویش مشخص شوی نه وي، مګر د UnityEngine.Random.Range() سره په ورته والي سره، یو یونیفورم ویش هم تمه کیده) او Unity.Mathematics.Random.NextFloat() (کوم چې د xorshift الګوریتم پر بنسټ والړ دی، پدې معنی چې یو یونیفورم ویش باید بیا تمه شي).
په ډیفالټ ډول، تمه شوې پایلې هغه وې چې په اسنادو کې مشخص شوي وې.
میتودولوژي
موږ یو کوچنی اپلیکېشن ولیکه چې د وړاندې شویو میتودونو په کارولو سره یې د تصادفي شمېرو ترتیبونه رامینځته کړل او پایلې یې د نورو پروسس کولو لپاره ذخیره کړې.
د هرې لړۍ اوږدوالی ۱۰۰،۰۰۰ عددونه دي.
د تصادفي شمېرو ارزښتونو لړۍ [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 معیاري 2.0
پلي کول
موږ د تصادفي شمېرو د تولید لپاره څو مختلفې لارې لرو. د هر یو لپاره، موږ به یو جلا ریپر کلاس ولیکو چې باید چمتو کړي:
- د ارزښتونو د یوې لړۍ د مشخص کولو امکان [لږترلږه/ اعظمي). د جوړونکي له لارې به تنظیم شي.
- یوه طریقه چې یوه شمیره بیرته راګرځوي. موږ به د ډول په توګه float غوره کړو، ځکه چې دا ډیر عمومي دی.
- د پایلو د لیبل کولو لپاره د نسل میتود نوم. د اسانتیا لپاره، موږ به د بشپړ ټولګي نوم + د هغه میتود نوم بیرته ورکړو چې د ارزښت په توګه د SC تولید لپاره کارول کیږي.
لومړی، راځئ چې یو تجرید اعلان کړو چې د IRandomGenerator انٹرفیس لخوا به استازیتوب شي:
namespace RandomDistribution
{
public interface IRandomGenerator
{
string Name { get; }
float Generate();
}
}د System.Random.Next() پلي کول
دا طریقه تاسو ته اجازه درکوي چې د ارزښتونو یو لړ مشخص کړئ، مګر دا انټیجرونه بیرته راګرځوي، پداسې حال کې چې فلوټس اړین دي. تاسو کولی شئ په ساده ډول انټیجر د فلوټ په توګه تشریح کړئ، یا تاسو کولی شئ د ارزښتونو لړۍ د اندازې څو ترتیبونو سره پراخه کړئ، هرکله چې فریکونسي رامینځته کیږي د دوی لپاره تاوان ورکړئ. دا به د دقیقیت د ټاکل شوي ترتیب سره د ثابت ټکي په څیر یو څه پایله ولري. موږ به دا اختیار وکاروو، ځکه چې دا د ریښتیني فلوټ ارزښت ته نږدې دی.
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;
}
}د System.Random.NextDouble() پلي کول
دلته د ارزښتونو ثابت حد [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;
}
}د UnityEngine.Random.Range() پلي کول
د سټیټیک یونیټي انجن. رینډم ټولګي دا طریقه تاسو ته اجازه درکوي چې د ارزښتونو لړۍ مشخص کړئ او د فلوټ ډوله تصادفي شمیره بیرته راګرځوئ. هیڅ اضافي تبادلې ته اړتیا نشته.
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;
}
}د یووالي. ریاضي. تصادفي. راتلونکی فلوټ () پلي کول
د Unity.Mathematics.Random ټولګي د NextFloat() میتود د فلوټ تصادفي شمیره بیرته راګرځوي او تاسو ته اجازه درکوي چې د ارزښتونو لړۍ مشخص کړئ. یوازینۍ احتیاط دا دی چې د Unity.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);
}
}د اصلي کنټرولر پلي کول
د IRandomGenerator څو تطبیقونه چمتو دي. بیا، موږ اړتیا لرو چې ترتیبونه تولید کړو او پایله لرونکی ډیټاسیټ د پروسس کولو لپاره خوندي کړو. د دې کولو لپاره، موږ به په یونیټي کې یو صحنه او یو کوچنی مین کنټرولر سکریپټ جوړ کړو چې ټول اړین کار به ترسره کړي او د UI تعامل به اداره کړي.
موږ به د ډیټاسیټ اندازه او د فریکونسي ارزښتونو لړۍ تعریف کړو، او همدارنګه به داسې طریقه جوړه کړو چې د ترتیب شوي او کارولو لپاره چمتو جنراتورونو لړۍ بیرته راولي.
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();
}
}
...
}
}د پروژې سرچینې په لاندې ډول دي: .
پایلې
هیڅ معجزه نه وه. موږ هغه څه ترلاسه کړل چې موږ یې تمه درلوده - په ټولو قضیو کې یو شان ویش، د دسیسې هیڅ نښه پرته. زه د جلا پلیټ فارم چارټونو ضمیمه کولو کې هیڅ معنی نه وینم - دوی ټول تقریبا ورته پایلې ښیې.
حقیقت دا دی:

د ټولو پنځو نسلي میتودونو څخه په یوه الوتکه کې د ترتیبونو لیدل:

او درې بعدي لید. زه به یوازې د System.Random.Next() پایله پریږدم ترڅو د ورته محتوا د ډیریدو مخه ونیسم.

هغه کیسه چې په سریزه کې د UnityEngine د نورمال ویش په اړه ویل شوې وه. ناڅاپه ځان تکرار نه کړ: یا دا له پیل څخه نیمګړتیا وه، یا له هغه وخت راهیسې په انجن کې یو څه بدل شوی دی. مګر اوس موږ ډاډه یو.
سرچینه: www.habr.com
