مولد أرقام عشوائية في جافا سكريبت قابل للتعيين بالبذور
وظيفة JavaScript Math.random() ترجع قيمة عشوائية بين 0 و 1، يتم تعيين البذرة لها تلقائيًا بناءً على الوقت الحالي (مماثل لما أعتقد في Java). ومع ذلك، لا أعتقد أن هناك أي طريقة لتحديد بذرة خاصة بك لها.
كيف يمكنني إنشاء مولد أرقام عشوائية يمكنني تزويده بقيمة بذرة خاصة بي، بحيث يمكنني جعله ينتج تسلسلاً قابلاً للتكرار من الأرقام (شبه) العشوائية؟
الإجابة رقم 1
إذا لم تكن بحاجة إلى القدرة على التمهيد، فقط استخدم Math.random() وابنِ دوال مساعدة حوله (مثلاً randRange(start, end)).
لست متأكدًا من مولد الأرقام العشوائية الذي تستخدمه، لكنه من الأفضل أن تعرفه وتوثقه حتى تكون على دراية بخصائصه وقيوده.
كما قال ستاركي، مولد الأعداد العشوائية ميرسين تورستر جيد، لكنه ليس سهل التنفيذ. إذا كنت تريد القيام بذلك بنفسك، حاول تنفيذ مولد خطي متسلسل (LCG) - إنه سهل جدًا، وله خصائص عشوائية معقولة (ليس جيدًا مثل ميرسين تورستر)، ويمكنك استخدام بعض الثوابت الشائعة.
تعديل: ضع في الاعتبار الخيارات الرائعة في هذا الجواب لتنفيذ مولد أعداد عشوائية قصير وقابل للزرع، بما في ذلك خيار LCG.
function RNG(seed) {
// LCG using GCC's constants
this.m = 0x80000000; // 2**31;
this.a = 1103515245;
this.c = 12345;
this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
}
RNG.prototype.nextInt = function() {
this.state = (this.a * this.state + this.c) % this.m;
return this.state;
}
RNG.prototype.nextFloat = function() {
// returns in range [0,1]
return this.nextInt() / (this.m - 1);
}
RNG.prototype.nextRange = function(start, end) {
// returns in range [start, end): including start, excluding end
// can't modulu nextInt because of weak randomness in lower bits
var rangeSize = end - start;
var randomUnder1 = this.nextInt() / this.m;
return start + Math.floor(randomUnder1 * rangeSize);
}
RNG.prototype.choice = function(array) {
return array[this.nextRange(0, array.length)];
}
var rng = new RNG(20);
for (var i = 0; i < 10; i++)
console.log(rng.nextRange(10, 50));
var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
for (var i = 0; i < 10; i++)
console.log(rng.choice(digits));الإجابة رقم 2
إذا كنت تريد أن تكون قادرًا على تحديد البذرة، فقط تحتاج إلى استبدال الاستدعاءات إلى getSeconds() وgetMinutes(). يمكنك تمرير عدد صحيح واستخدام نصفه modulo 60 لقيمة الثواني والنصف الآخر modulo 60 لإعطائك الجزء الآخر.
مع ذلك، تبدو هذه الطريقة كأنها هراء. توليد الأرقام العشوائية بشكل صحيح أمر صعب للغاية. المشكلة الواضحة هنا هي أن البذرة للأرقام العشوائية تعتمد على الثواني والدقائق. لتخمين البذرة وإعادة إنشاء تدفقك من الأرقام العشوائية، يكفي تجربة 3600 تركيبة مختلفة من الثواني والدقائق. وهذا يعني أيضًا أن هناك 3600 بذرة محتملة فقط. يمكن تصحيح هذا، لكنني سأكون متشككًا بشأن هذا المولد العشوائي منذ البداية.
إذا كنت تريد استخدام مولد أرقام عشوائية أفضل، جرب مرسن تويستر. إنه مولد أرقام عشوائية مُختبر جيدًا وقوي إلى حد كبير مع مدار ضخم وأداء ممتاز.
تعديل: يجب عليّ في الواقع أن أكون دقيقًا وأن أشير إلى هذا باعتباره مولد أرقام عشوائية زائف أو PRNG.
&
الإجابة رقم 3
أستخدم نسخة جافا سكريبت من مولد مرسن-توستر: https://gist.github.com/300494 يسمح لك بتعيين البذرة يدويًا. أيضًا، كما ذُكر في إجابات أخرى، فإن مرسن-توستر هو مولد أرقام عشوائية جيد جدًا.
