คำถามนี้กว้างเกินไปสำหรับคำตอบที่สมบูรณ์ แต่ขอให้ฉันเลือกประเด็นที่น่าสนใจสองสามข้อ:
ทำไม "มีโอกาสเท่ากัน"
สมมติว่าคุณมีตัวสร้างตัวเลขสุ่มอย่างง่ายที่สร้างตัวเลข 0, 1, ... , 10 แต่ละตัวที่มีความน่าจะเป็นเท่ากัน (คิดว่านี่คือคลาสสิกrand()
) ตอนนี้คุณต้องการตัวเลขสุ่มในช่วง 0, 1, 2 ซึ่งแต่ละตัวมีความน่าจะเป็นเท่ากัน ปฏิกิริยากระตุกเข่าของคุณจะเกิดrand() % 3
ขึ้น แต่เดี๋ยวก่อนส่วนที่เหลือ 0 และ 1 เกิดขึ้นบ่อยกว่าส่วนที่เหลือ 2 ดังนั้นจึงไม่ถูกต้อง!
นี่คือเหตุผลที่เราต้องการการแจกแจงที่เหมาะสมซึ่งใช้แหล่งที่มาของจำนวนเต็มสุ่มที่สม่ำเสมอและเปลี่ยนเป็นการแจกแจงที่เราต้องการUniform[0,2]
ดังตัวอย่าง ดีที่สุดที่จะฝากไว้ในห้องสมุดดีๆ!
เครื่องยนต์
ดังนั้นหัวใจสำคัญของการสุ่มทั้งหมดคือเครื่องกำเนิดตัวเลขสุ่มหลอกที่ดีที่สร้างลำดับของตัวเลขที่กระจายอย่างสม่ำเสมอในช่วงเวลาหนึ่งและซึ่งควรมีช่วงเวลาที่ยาวนานมาก การใช้งานมาตรฐานrand()
มักไม่ใช่สิ่งที่ดีที่สุดดังนั้นจึงเป็นการดีที่จะมีทางเลือก Linear-Congruential และ Mersenne twister เป็นสองทางเลือกที่ดี (LG มักใช้ด้วยrand()
เช่นกัน); อีกครั้งเป็นเรื่องดีที่จะให้ห้องสมุดจัดการเรื่องนั้น
มันทำงานอย่างไร
ง่าย: ขั้นแรกติดตั้งเครื่องยนต์และเพาะเมล็ด เมล็ดพันธุ์จะกำหนดลำดับทั้งหมดของตัวเลข "สุ่ม" ดังนั้น a) ใช้หมายเลขอื่น (เช่นนำมาจาก/dev/urandom
) ในแต่ละครั้งและ b) เก็บเมล็ดพันธุ์ไว้หากคุณต้องการสร้างลำดับของตัวเลือกแบบสุ่มขึ้นมาใหม่
#include <random>
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng; // e.g. keep one global instance (per thread)
void initialize()
{
rng.seed(seed_val);
}
ตอนนี้เราสามารถสร้างการกระจาย:
std::uniform_int_distribution<uint32_t> uint_dist; // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation); // N(mean, stddeviation)
... และใช้เครื่องยนต์เพื่อสร้างตัวเลขสุ่ม!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
ภาวะพร้อมกัน
เหตุผลที่สำคัญอีกประการหนึ่งที่ชอบ<random>
มากกว่าแบบดั้งเดิมrand()
คือตอนนี้มีความชัดเจนและชัดเจนว่าจะสร้างเธรดการสร้างตัวเลขแบบสุ่มได้อย่างไร: ให้แต่ละเธรดมีเอ็นจิ้นเธรดโลคัลของตัวเองติดตั้งบนเธรดโลคัลหรือซิงโครไนซ์การเข้าถึง ไปยังวัตถุเครื่องยนต์
อื่น ๆ
- บทความที่น่าสนใจใน TR1 สุ่ม CodeGuru
- Wikipediaมีบทสรุปที่ดี (ขอบคุณ @Justin)
- โดยหลักการแล้วเครื่องยนต์แต่ละตัวควรพิมพ์คำว่า a
result_type
ซึ่งเป็นประเภทอินทิกรัลที่ถูกต้องเพื่อใช้สำหรับเมล็ดพันธุ์ ฉันคิดว่าฉันมีการใช้งานบั๊กกี้ครั้งหนึ่งซึ่งบังคับให้ฉันบังคับให้เมล็ดพันธุ์std::mt19937
ไปuint32_t
ที่ x64 ในที่สุดสิ่งนี้ควรได้รับการแก้ไขและคุณสามารถพูดได้MyRNG::result_type seed_val
และทำให้เครื่องยนต์เปลี่ยนได้ง่ายมาก
rand
คุณควรดูวิกิพีเดียอย่างรวดเร็วสำหรับแนวคิดพื้นฐานทางสถิติและ RNG มิฉะนั้นจะเป็นการยากที่จะอธิบายให้คุณทราบถึงเหตุผล<random>
และการใช้งานชิ้นส่วนต่างๆ