आपके परीक्षण आवेदन की सबसे बुनियादी समस्या यह है कि आप srand
एक बार कॉल करते हैं और फिर rand
एक बार कॉल करते हैं और बाहर निकलते हैं।
srand
फ़ंक्शन का पूरा बिंदु यादृच्छिक बीज के साथ छद्म यादृच्छिक संख्याओं के अनुक्रम को प्रारंभ करना है ।
इसका मतलब यह है कि यदि आप एक ही मूल्य को srand
दो अलग-अलग अनुप्रयोगों (एक ही srand
/ rand
कार्यान्वयन के साथ) में पास करते हैं तो आपकोrand()
दोनों अनुप्रयोगों में उसके बाद के मूल्यों के समान अनुक्रम प्राप्त होंगे ।
हालाँकि आपके उदाहरण में आवेदन छद्म यादृच्छिक अनुक्रम में केवल एक तत्व होता है - एक छद्म यादृच्छिक अनुक्रम का पहला तत्व जो बीज से second
सटीक और वर्तमान समय के बराबर होता है । फिर आउटपुट पर क्या देखने की उम्मीद है?
जाहिर है जब आप एक ही सेकंड में आवेदन चलाने के लिए होते हैं - आप एक ही बीज मूल्य का उपयोग करते हैं - इस प्रकार आपका परिणाम पाठ्यक्रम का एक ही है (जैसा कि मार्टिन यॉर्क ने पहले ही सवाल का एक टिप्पणी में उल्लेख किया है)।
वास्तव में आपको srand(seed)
एक बार कॉल करना चाहिए और फिर rand()
कई बार कॉल करना चाहिए और उस अनुक्रम का विश्लेषण करना चाहिए - यह यादृच्छिक दिखना चाहिए।
संपादित करें:
अच्छा मैं समझा। स्पष्ट रूप से मौखिक विवरण पर्याप्त नहीं है (शायद भाषा बाधा या कुछ और ... :))।
ठीक है। पुराने जमाने के सी कोड उदाहरण उन्हीं srand()/rand()/time()
कार्यों पर आधारित है जिनका उपयोग प्रश्न में किया गया था:
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main(void)
{
unsigned long j;
srand( (unsigned)time(NULL) );
for( j = 0; j < 100500; ++j )
{
int n;
/* skip rand() readings that would make n%6 non-uniformly distributed
(assuming rand() itself is uniformly distributed from 0 to RAND_MAX) */
while( ( n = rand() ) > RAND_MAX - (RAND_MAX-5)%6 )
{ /* bad value retrieved so get next one */ }
printf( "%d,\t%d\n", n, n % 6 + 1 );
}
return 0;
}
^^^ कि कार्यक्रम की एक एकल रन से अनुक्रम यादृच्छिक देखने के लिए माना जाता है।
EDIT2:
C या C ++ मानक पुस्तकालय का उपयोग करते समय यह समझना महत्वपूर्ण है कि अब तक एक भी मानक फ़ंक्शन या वर्ग नहीं है जो वास्तव में यादृच्छिक डेटा निश्चित रूप से (मानक द्वारा गारंटीकृत) उत्पन्न करता है। एकमात्र मानक उपकरण जो इस समस्या से संपर्क करता है वह है std :: random_device जो दुर्भाग्य से अभी भी वास्तविक यादृच्छिकता की गारंटी नहीं देता है।
आवेदन की प्रकृति के आधार पर आपको पहले यह तय करना चाहिए कि क्या आपको वास्तव में यादृच्छिक (अप्रत्याशित) डेटा की आवश्यकता है। उल्लेखनीय मामला जब आपको निश्चित रूप से सच्ची यादृच्छिकता की आवश्यकता होती है तो सूचना सुरक्षा है - जैसे कि सममित कुंजी, असममित निजी कुंजी, नमक मान, सुरक्षा टोकन, आदि।
हालांकि सुरक्षा-ग्रेड यादृच्छिक संख्या एक अलग लेख के लायक एक अलग उद्योग है।
ज्यादातर मामलों में छद्म-यादृच्छिक संख्या जनरेटर पर्याप्त है - जैसे वैज्ञानिक सिमुलेशन या खेल के लिए। कुछ मामलों में लगातार परिभाषित छद्म यादृच्छिक क्रम की आवश्यकता होती है - उदाहरण के लिए, खेल में आप बहुत सारे डेटा के भंडारण से बचने के लिए रनटाइम में बिल्कुल एक ही नक्शे उत्पन्न करने के लिए चुन सकते हैं।
मूल प्रश्न और समरूप / समान प्रश्नों (और यहां तक कि कई गुमराह "उत्तरों" की पुनरावृत्ति की भीड़) से संकेत मिलता है कि सबसे पहले और सबसे महत्वपूर्ण यह है कि छद्म यादृच्छिक संख्याओं से यादृच्छिक संख्याओं को अलग करना और समझने के लिए कि छद्म यादृच्छिक संख्या अनुक्रम क्या है। पहली जगह और यह महसूस करने के लिए कि छद्म यादृच्छिक संख्या जनरेटर का उपयोग उसी तरह नहीं किया जाता है जिस तरह से आप सच्चे यादृच्छिक संख्या जनरेटर का उपयोग कर सकते हैं।
सहज रूप से जब आप यादृच्छिक संख्या का अनुरोध करते हैं - परिणाम लौटाया जाना चाहिए पहले से दिए गए मूल्यों पर निर्भर नहीं होना चाहिए और यह निर्भर नहीं करना चाहिए कि किसी ने पहले किसी भी चीज का अनुरोध किया है और किस क्षण और किस प्रक्रिया से और किस कंप्यूटर पर और किस जनरेटर से और में निर्भर होना चाहिए क्या आकाशगंगा यह अनुरोध किया गया था। यही कारण है कि शब्द "यादृच्छिक" का मतलब आखिरकार है - अप्रत्याशित और किसी भी चीज से स्वतंत्र होना - अन्यथा यह यादृच्छिक नहीं है, है ना? इस अंतर्ज्ञान के साथ किसी भी संभावित संदर्भ में इस तरह के यादृच्छिक संख्या प्राप्त करने के लिए कुछ जादू मंत्रों के लिए वेब खोजना केवल प्राकृतिक है।
^ ^ ^ इन सहज तरह की अपेक्षाएं बहुत गलत हैं और छद्म-यादृच्छिक संख्या जनरेटरों से जुड़े सभी मामलों में हानिकारक हैं - सही यादृच्छिक संख्याओं के लिए उचित होने के बावजूद।
जबकि "यादृच्छिक संख्या" की सार्थक धारणा मौजूद है - "छद्म यादृच्छिक संख्या" जैसी कोई चीज नहीं है। एक छद्म यादृच्छिक संख्या जनरेटर वास्तव में छद्म यादृच्छिक संख्या अनुक्रम पैदा करता है ।
जब विशेषज्ञ PRNG की गुणवत्ता के बारे में बात करते हैं तो वे वास्तव में उत्पन्न अनुक्रम के सांख्यिकीय गुणों (और इसके उल्लेखनीय उप-अनुक्रमों) के बारे में बात करते हैं। उदाहरण के लिए यदि आप दो उच्च गुणवत्ता वाले PRNGs को बारी-बारी से दोनों का उपयोग करके जोड़ते हैं - तो आप खराब परिणामी अनुक्रम उत्पन्न कर सकते हैं - उनके बावजूद अलग-अलग अच्छे क्रम उत्पन्न करने के बावजूद (वे दो अच्छे क्रम बस एक-दूसरे से संबद्ध हो सकते हैं और इस प्रकार बुरी तरह से संयोजित हो सकते हैं)।
छद्म यादृच्छिक अनुक्रम वास्तव में हमेशा नियतात्मक होता है (इसके एल्गोरिथ्म और प्रारंभिक मापदंडों द्वारा पूर्वनिर्धारित) यानी वास्तव में इसके साथ यादृच्छिक कुछ भी नहीं है।
विशेष रूप से rand()
/ srand(s)
कार्यों की जोड़ी कार्यान्वयन-परिभाषित एल्गोरिथ्म के साथ उत्पन्न एक एकल प्रति-प्रक्रिया गैर-थ्रेड-सुरक्षित (!) छद्म यादृच्छिक संख्या अनुक्रम प्रदान करती है। समारोह rand()
रेंज में मूल्यों का उत्पादन करता है [0, RAND_MAX]
।
C11 मानक से उद्धरण:
srand
समारोह छद्म यादृच्छिक संख्या का एक नया अनुक्रम को आगामी कॉल द्वारा दिए जाते के लिए एक बीज के रूप में तर्क का उपयोग करता है rand
। यदि
srand
इसे उसी बीज मूल्य के साथ कहा जाता है, तो छद्म यादृच्छिक संख्याओं का क्रम दोहराया जाएगा। यदि rand
कोई कॉल किए जाने से पहले बुलाया जाता srand
है, तो उसी क्रम को उत्पन्न किया जाएगा जब srand
पहली बार 1 के बीज मान के साथ कहा जाता है।
बहुत से लोग काफी उम्मीद करते हैं कि rand()
रेंज में अर्द्ध स्वतंत्र समान रूप से वितरित संख्या का एक अनुक्रम का उत्पादन 0
करने के लिए RAND_MAX
। अच्छी तरह से यह निश्चित रूप से होना चाहिए (अन्यथा यह बेकार है) लेकिन दुर्भाग्य से न केवल मानक की आवश्यकता नहीं है - यहां तक कि स्पष्ट अस्वीकरण भी है जो बताता है कि "उत्पादित यादृच्छिक अनुक्रम की गुणवत्ता के लिए कोई गारंटी नहीं है" । कुछ ऐतिहासिक मामलों में rand
/ srand
कार्यान्वयन वास्तव में बहुत खराब गुणवत्ता का था। भले ही आधुनिक कार्यान्वयन में यह सबसे अच्छा होने की संभावना है - लेकिन भरोसा टूट गया है और ठीक होना आसान नहीं है। इसके गैर-थ्रेड-सुरक्षित प्रकृति के अलावा बहु-थ्रेडेड अनुप्रयोगों में इसका सुरक्षित उपयोग मुश्किल और सीमित (अभी भी संभव है - आप उन्हें केवल एक समर्पित धागे से उपयोग कर सकते हैं)।
नया वर्ग टेम्पलेट एसटीडी :: mersenne_twister_engine <> (और इसकी सुविधा टाइप्डिफ़्स - std::mt19937
/ std::mt19937_64
अच्छे टेम्पलेट पैरामीटर संयोजन के साथ) C ++ 11 मानक में परिभाषित प्रति-वस्तु छद्म यादृच्छिक संख्या जनरेटर प्रदान करता है । समान टेम्प्लेट पैरामीटर्स और समान इनिशियलाइज़ेशन पैरामीटर्स के साथ, विभिन्न ऑब्जेक्ट्स C ++ 11 कंप्लेंट स्टैंडर्ड लाइब्रेरी के साथ बनाए गए किसी भी एप्लिकेशन में किसी भी कंप्यूटर पर बिल्कुल समान ऑब्जेक्ट-ऑब्जेक्ट आउटपुट सीक्वेंस उत्पन्न करेंगे। इस वर्ग का लाभ इसके उच्च गुणवत्ता वाले आउटपुट अनुक्रम और कार्यान्वयन के दौरान पूर्ण स्थिरता है।
इसके अलावा C + 11 मानक में परिभाषित PRNG इंजन अधिक हैं - std :: linear_congruential_engine <> (ऐतिहासिक रूप srand/rand
से कुछ सी मानक पुस्तकालय कार्यान्वयन में उचित गुणवत्ता एल्गोरिथ्म के रूप में इस्तेमाल किया जाता है ) और std :: subtract_with_carine_engine <> । वे पूरी तरह से परिभाषित पैरामीटर-निर्भर प्रति-ऑब्जेक्ट आउटपुट अनुक्रम भी उत्पन्न करते हैं।
उपरोक्त अप्रचलित सी कोड के लिए आधुनिक दिन C ++ 11 उदाहरण प्रतिस्थापन:
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
// seed value is designed specifically to make initialization
// parameters of std::mt19937 (instance of std::mersenne_twister_engine<>)
// different across executions of application
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
for( unsigned long j = 0; j < 100500; ++j )
/* ^^^Yes. Generating single pseudo-random number makes no sense
even if you use std::mersenne_twister_engine instead of rand()
and even when your seed quality is much better than time(NULL) */
{
std::mt19937::result_type n;
// reject readings that would make n%6 non-uniformly distributed
while( ( n = gen() ) > std::mt19937::max() -
( std::mt19937::max() - 5 )%6 )
{ /* bad value retrieved so get next one */ }
std::cout << n << '\t' << n % 6 + 1 << '\n';
}
return 0;
}
पिछले कोड का संस्करण जो std :: वर्दी_int_distribution <> का उपयोग करता है
#include <iostream>
#include <chrono>
#include <random>
int main()
{
std::random_device rd;
std::mt19937::result_type seed = rd() ^ (
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() +
(std::mt19937::result_type)
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count() );
std::mt19937 gen(seed);
std::uniform_int_distribution<unsigned> distrib(1, 6);
for( unsigned long j = 0; j < 100500; ++j )
{
std::cout << distrib(gen) << ' ';
}
std::cout << '\n';
return 0;
}