مشكلات مع البذر مولد رقم عشوائي الزائفة أكثر من مرة؟

StackOverflow https://stackoverflow.com/questions/976993

سؤال

لقد رأيت عددا قليلا جدا من التوصيات لعدم البذر من مولدات الأرقام العشوائية الزائفة أكثر من مرة لكل عملية تنفيذ، ولكن لا يرافقه شرح شامل. بالطبع، من السهل معرفة سبب سبيل المثال التالي (C / C ++) فكرة جيدة:

int get_rand() {
  srand(time(NULL));
  return rand();
}

منذ الدعوة get_rand عدة مرات في الثانية تنتج نتائج متكررة.

ولكن لن يكون المثال التالي هو حل مقبول؟

myrand.h.

#ifndef MY_RAND_H
#define MY_RAND_H

class MyRand
{
  public:
    MyRand();
    int get_rand() const;
  private:
    static unsigned int seed_base;
};

#endif

myrand.cpp.

#include <ctime>
#include <cstdlib>
#include "MyRand.h"

unsigned int MyRand::seed_base = static_cast<unsigned int>(time(NULL));

MyRand::MyRand()
{
  srand(seed_base++);
}

int MyRand::get_rand() const
{
  return rand();
}

main.cpp.

#include <iostream>
#include "MyRand.h"

int main(int argc, char *argv[]) 
{
  for (int i = 0; i < 100; i++) 
  {
    MyRand r;
    std::cout << r.get_rand() << " ";
  }
}

أي على الرغم من MyRand: يسمى منشئ S عدة مرات في تتابع سريع، كل مكالمة srand لديه معلمة مختلفة. من الواضح أن هذا ليس آمنا للخيط، ولكن مرة أخرى لا rand.

هل كانت مفيدة؟

المحلول

في كل مرة تقوم فيها بالاتصال بوظيفة مولد عدد عشوائي عشوائي، يأخذ المولد بعض الحالة الداخلية وتنتج رقم عشوائي زائف ودولة داخلية جديدة. يتم اختيار خوارزمية تحويل الحالة الداخلية بعناية حتى يظهر الإخراج عشوائيا.

عندما تقوم بذرة مولد الأرقام العشوائية، فأنت تقوم بوضع هذه الحالة الداخلية بشكل أساسي. إذا قمت بإعادة تعيين الحالة الداخلية إلى بعض القيمة المتوقعة، فسوف تفقد ظهور العشوائي.

على سبيل المثال، شعبية، RNG بسيطة هو مولد متطور خطي. يتم إنشاء الأرقام مثل هذا:

X[n+1] = (a X[n] + c) mod m

في هذه الحالة، X [N + 1] هو كل من النتيجة والولاية الداخلية الجديدة. إذا قمت بتصفيف المولد في كل مرة كما تقترح أعلاه، فستحصل على تسلسل يشبه هذا:

{(ab + c) mod m, (a(b+1) + c) mod m, (a(b+2) + c) mod m, ...}

حيث ب هو الخاص بك seed_base. وبعد هذا لا يبدو عشوائيا على الإطلاق.

نصائح أخرى

إذا كانت بذورك يمكن التنبؤ بها، فسيكون هنا منذ زيادة ذلك، ستكون الإخراج من Rand () يمكن التنبؤ به أيضا.

يعتمد ذلك حقا على سبب رغبتك في إنشاء أرقام عشوائية، وكيف "عشوائي" هو عشوائي مقبول لك. في مثالك، قد يتجنب التكرارات في الخلافة السريعة، وقد يكون ذلك جيدا بما يكفي بالنسبة لك. بعد كل شيء، ما يهم هو أنه يعمل.

على كل منصة تقريبا، هناك طريقة أفضل لتوليد أرقام عشوائية من Rand ().

حسنا، إنها معالجة إضافية لا تحتاج إلى القيام به.

في هذا السيناريو، أود فقط استدعاء المنشئ مرة واحدة مع البذرة القائمة على الوقت قبل بدء الحلقة. من شأنها أن تضمن نتائج عشوائية دون الحمل الزائد من البذور المتغيرة لكل تكرار.

لا أعتقد أن طريقتك هي أي أكثر عشوائي من ذلك.

يمكنك التفكير في جيل الأرقام العشوائية (هذا ليس التنفيذ الحقيقي بشكل صارم - من الحكمة، ولكن بمثابة توضيح) كجدول من القيم. إذا كنت تتذكر القيام بأي من هذه الأشياء في إحصائيات القيام بعينات عشوائية بسيطة، فإن البذرة تخبرك أساسا ما هو الصف والعمود للبدء في جدولك الكبير لأرقام عشوائية. من جديد مرارا وتكرارا هو ببساطة غير ضرورية لأننا يمكن أن نفترض بالفعل أن الأرقام موزعة عادة بالفعل.

لا يوجد ببساطة فائدة إضافية للبذر أكثر من مرة لأن هذا يجب أن يكون جيدا بما فيه الكفاية (اعتمادا على التطبيق). إذا كنت بحاجة إلى أرقام عشوائية "أكثر"، فهناك العديد من أساليب جيل الأرقام العشوائية. إحدى الحالات التي يمكنني التفكير فيها هي إنشاء أرقام عشوائية بطريقة آمنة للخيط.

في حين أن الحل الخاص بك مقبول، فإن أرقامك لن تكون عشوائية أكثر عشوائية من البذور مرة واحدة، على الصعيد العالمي. Srand عموما لا ينبغي أن تنتمي إلى منشئ. إذا كنت ترغب في دعم الأرقام العشوائية، والبذور مرة واحدة عندما يبدأ البرنامج، ونسيانها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top