এই উদাহরণ কোডটি চিত্রিত করে যে std::rand
লিগ্যাসি কার্গো কাল্ট বাল্ডারড্যাশের একটি ঘটনা যা আপনার ভ্রুকে যতবার দেখা হবে ততবার বাড়িয়ে তুলবে।
এখানে বেশ কয়েকটি সমস্যা রয়েছে:
চুক্তির লোকেরা সাধারণত ধরে নেয় - এমনকি দরিদ্র অসহায় আত্মারা যারা আরও ভাল জানেন না এবং অবিকল এই পদগুলিতে এটি ভাববেন না won't তা হল 0, 1, 2,…,, তে পূর্ণসংখ্যার উপর অভিন্ন বিতরণrand
থেকে প্রাপ্ত নমুনাগুলি , এবং প্রতিটি কল একটি স্বতন্ত্র নমুনা দেয়।RAND_MAX
প্রথম সমস্যাটি হ'ল ধারণা করা চুক্তি, প্রতিটি কলটিতে স্বতন্ত্র ইউনিফর্মের এলোমেলো নমুনাগুলি আসলে ডকুমেন্টেশন বলে না not এবং বাস্তবে বাস্তবায়নগুলি historতিহাসিকভাবে স্বাধীনতার এমনকি বেস্ট সিমুলাক্রাম সরবরাহ করতে ব্যর্থ হয়েছিল। উদাহরণস্বরূপ, C99 §7.20.2.1 ' rand
ফাংশন' বলছে, বিনা ছাড়াই:
rand
ফাংশন পরিসীমা 0 মধ্যে সিউডো-রেণ্ডম পূর্ণসংখ্যার একটি ক্রম নির্ণয় RAND_MAX
।
এটি অর্থহীন বাক্য, কারণ সিউডোর্যান্ডমনেস কোনও ক্রিয়াকলাপের (বা ফাংশনগুলির পরিবার ) এর সম্পত্তি, কোনও পূর্ণসংখ্যার নয়, তবে এটি আইএসও আমলাগুলিকে ভাষা অপব্যবহার করা থেকে বিরত রাখে না। সর্বোপরি, একমাত্র পাঠক যারা এর দ্বারা বিচলিত হবেন rand
তাদের মস্তিষ্কের কোষগুলি ক্ষয় হওয়ার ভয়ে ডকুমেন্টেশন পড়ার চেয়ে আরও ভাল জানেন ।
সিতে একটি সাধারণ historicalতিহাসিক বাস্তবায়ন এইভাবে কাজ করে:
static unsigned int seed = 1;
static void
srand(unsigned int s)
{
seed = s;
}
static unsigned int
rand(void)
{
seed = (seed*1103515245 + 12345) % ((unsigned long)RAND_MAX + 1);
return (int)seed;
}
এটিতে দুর্ভাগ্যজনক সম্পত্তি রয়েছে যে যদিও একটি একক নমুনা অভিন্ন র্যান্ডম বীজের অধীনে একত্রে বিতরণ করা যেতে পারে (যা এর নির্দিষ্ট মানের উপর নির্ভর করে RAND_MAX
), এটি পরপর কলগুলিতে সমান এবং বিজোড় পূর্ণসংখ্যার মধ্যে বিকল্প হয় — পরে
int a = rand();
int b = rand();
(a & 1) ^ (b & 1)
100% সম্ভাব্যতার সাথে অভিব্যক্তিটি 1 দেয়, যা সমান এবং বিজোড় পূর্ণসংখ্যার উপর সমর্থনযুক্ত কোনও বিতরণে স্বতন্ত্র এলোমেলো নমুনার ক্ষেত্রে নয় । সুতরাং, একটি কার্গো ধর্মগুচ্ছ উত্থিত হয়েছিল যে 'উন্নত র্যান্ডমনেস' এর অধরা জন্তুটিকে তাড়া করার জন্য লো-অর্ডার বিটগুলি ফেলে দেওয়া উচিত। (স্পোলার সতর্কতা: এটি কোনও প্রযুক্তিগত শব্দ নয় This এটি এমন একটি চিহ্ন যা আপনি যে গদ্যটি পড়ছেন তা তারা কীসের বিষয়ে কথা বলছেন তা জানে না বা মনে করে যে আপনি নিখরচায় রয়েছেন এবং অবশ্যই তাকে অবজ্ঞা করা উচিত))
দ্বিতীয় সমস্যাটি হ'ল এমনকি যদি প্রতিটি কল 0, 1, 2,…, এ অভিন্ন র্যান্ডম বিতরণ থেকে স্বতন্ত্রভাবে নমুনা দেয়RAND_MAX
তবে ফলাফলটি rand() % 6
ডাই এর মতো 0, 1, 2, 3, 4, 5 এ অভিন্নভাবে বিতরণ করা হত না রোল, যদি না RAND_MAX
-1 মডুলো to এর সাথে একত্রে হয় coun সরল পাল্টা নমুনা : যদি RAND_MAX
=, হয় তবে তার থেকে rand()
সমস্ত ফলাফলের সমান সম্ভাবনা থাকে 1/7, তবে এর থেকে rand() % 6
ফলাফল 0 এর সম্ভাব্যতা 2/7 থাকে এবং অন্য সমস্ত ফলাফলের সম্ভাব্যতা থাকে 1/7 ।
এটি করার সঠিক উপায় হ'ল প্রত্যাখ্যানের নমুনা সহ: বার বারs
0, 1, 2,…, থেকে একটি স্বতন্ত্র ইউনিফর্মের এলোমেলো নমুনা আঁকুন RAND_MAX
এবং প্রত্যাখ্যান করুন (উদাহরণস্বরূপ) ফলাফলগুলি 0, 1, 2,…, ((RAND_MAX + 1) % 6) - 1
- যদি আপনি একটি পেয়ে থাকেন তবে যারা, আবার শুরু; অন্যথায়, ফলন s % 6
।
unsigned int s;
while ((s = rand()) < ((unsigned long)RAND_MAX + 1) % 6)
continue;
return s % 6;
এইভাবে, rand()
যে ফলাফলগুলি আমরা গ্রহণ করি তার ফলাফলগুলি by দ্বারা সমানভাবে বিভাজ্য, এবং এর প্রতিটি সম্ভাব্য ফলাফল s % 6
একই সংখ্যক গৃহীত ফলাফলগুলি দ্বারা প্রাপ্ত হয় rand()
, সুতরাং যদি rand()
অভিন্নভাবে বিতরণ করা হয় তবে তাই হয় s
। পরীক্ষার সংখ্যার উপর কোনও আবদ্ধ নেই , তবে প্রত্যাশিত সংখ্যা 2 এর চেয়ে কম এবং সাফল্যের সম্ভাবনা বিচারের সংখ্যা সহকারে তাত্পর্যপূর্ণভাবে বৃদ্ধি পায়।
পছন্দমত যা ফলাফলের যুগ্ম rand()
আপনি প্রত্যাখ্যান অশরীরী দেওয়া যে আপনার 6. নীচের প্রতিটি পূর্ণসংখ্যা তাদের একটি সমান সংখ্যা মানচিত্র cppreference.com এ কোড একটি করে তোলে বিভিন্ন প্রথম সমস্যা হওয়ার কারণে, পছন্দ ওপরে যে কিছুই নিশ্চিত করা হয় বিতরণ বা ফলাফলের আউটপুটগুলির স্বাধীনতা rand()
এবং অনুশীলনে নিম্ন-অর্ডার বিটগুলি প্রদর্শিত প্রদর্শিত প্যাটার্নগুলিকে 'যথেষ্ট এলোমেলো মনে হয় না' (পরের আউটপুটটি পূর্বেরটির একটি ডিস্ট্রিমেন্টিক ফাংশন মনে করবেন না)।
পাঠকের জন্য অনুশীলন: প্রমাণ করুন যে সিপ্রেফারেন্স ডটকমের কোডটি ডাই রোলসের rand()
উপর 0, 1, 2,…, এর উপর অভিন্ন বিতরণ দেয় তবে ডাই রোলসের উপর একটি অভিন্ন বিতরণ দেয় RAND_MAX
।
পাঠকের জন্য অনুশীলন: আপনি কেন এক বা অন্য সাবটাকে প্রত্যাখ্যান করতে পছন্দ করতে পারেন? দুটি ক্ষেত্রে প্রতিটি বিচারের জন্য কোন গণনার প্রয়োজন?
তৃতীয় সমস্যাটি হ'ল বীজের স্থান এত কম যে এমনকি বীজটি সমানভাবে বিতরণ করা হলেও, একটি শত্রু আপনার প্রোগ্রামের জ্ঞান এবং একটি ফলাফলের সাথে সজ্জিত তবে বীজটি সহজেই বীজ এবং তার পরবর্তী ফলাফলগুলির পূর্বাভাস দিতে পারে, যার ফলে তারা এতটা মনে হয় না makes সব পরে এলোমেলো। এমনকি ক্রিপ্টোগ্রাফির জন্য এটি ব্যবহার করার কথা ভাবেন না।
আপনার চার বছর বয়সী মামাতো ভাইয়ের সাথে std::uniform_int_distribution
ডাইসে std::mt19937
খেলতে আপনি উপযুক্ত র্যান্ডম ডিভাইস এবং আপনার জনপ্রিয় এলোমেলো ইঞ্জিনের মতো জনপ্রিয় র্যান্ডম ইঞ্জিনের সাথে অভিনব ওভাররেঞ্জিনারিড রুট এবং সি ++ 11 এর ক্লাসে যেতে পারেন , তবে তাও যাচ্ছে না ক্রিপ্টোগ্রাফিক কী উপাদান তৈরির জন্য উপযুক্ত হতে পারেন — এবং মার্স্নিন টুইস্টার একটি সিএনপি-র একটি অশ্লীল সেটআপের সময় ক্যাশে মাল্টি-কিলোবাইট স্টেট বিধ্বস্ত করার সাথে একটি ভয়াবহ স্পেস হগও তাই এটি এমনকি খারাপ, যেমন সমান্তরাল মন্টি কার্লো সিমুলেশনগুলির সাথেও খারাপ is উপ-গুণাবলীর পুনরুত্পাদনযোগ্য গাছ; এটির জনপ্রিয়তা সম্ভবত আকর্ষণীয় নাম থেকেই উদ্ভূত হয়। তবে আপনি এটি খেলনা পাশা উদাহরণস্বরূপ ঘূর্ণায়মান জন্য ব্যবহার করতে পারেন!
আরেকটি পদ্ধতি হ'ল একটি ছোট রাষ্ট্রের সাথে একটি সাধারণ ক্রিপ্টোগ্রাফিক সিউডোর্যান্ডম সংখ্যার জেনারেটর ব্যবহার করা, যেমন একটি সহজ দ্রুত কী মুছে ফেলা পিআরএনজি , বা আপনি যদি আত্মবিশ্বাসী হন তবে এএসএস-সিটিআর বা চ্যাচ20 এর মতো একটি স্ট্রিম সাইফার ( যেমন , মন্টি কার্লো সিমুলেশনের জন্য) প্রাকৃতিক বিজ্ঞানের গবেষণা) যে রাষ্ট্র যদি কখনও আপস করে তবে অতীতের ফলাফল পূর্বাভাস দেওয়ার কোনও বিরূপ পরিণতি হয় না।
std::uniform_int_distribution