আপনার পরীক্ষার আবেদনের সর্বাধিক মৌলিক সমস্যাটি হ'ল আপনি srand
একবার কল করেছিলেন এবং তারপরে একবার কল করে rand
প্রস্থান করুন exit
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:
সি বা সি ++ স্ট্যান্ডার্ড লাইব্রেরি ব্যবহার করার সময় এটি বুঝতে গুরুত্বপূর্ণ যে এখন পর্যন্ত কোনও একক স্ট্যান্ডার্ড ফাংশন বা শ্রেণি প্রকৃতভাবে এলোমেলো ডেটা নির্ধারিতভাবে তৈরি করছে না (স্ট্যান্ডার্ড দ্বারা নিশ্চিত)। এই সমস্যাটির কাছে পৌঁছানোর একমাত্র মানক সরঞ্জামটি হল স্ট্যান্ড :: র্যান্ডম_ডভাইস যা দুর্ভাগ্যক্রমে এখনও সত্যিকারের এলোমেলোতার গ্যারান্টি সরবরাহ করে না।
অ্যাপ্লিকেশনটির প্রকৃতির উপর নির্ভর করে আপনার প্রথমে সিদ্ধান্ত নেওয়া উচিত যদি আপনার সত্যিকারের সত্যিকারের এলোমেলো (অনাকাঙ্ক্ষিত) ডেটা দরকার হয় কিনা। উল্লেখযোগ্য ক্ষেত্রে যখন আপনার অবশ্যই সত্যিকারের এলোমেলো প্রয়োজন হয় তা হ'ল তথ্য সুরক্ষা - যেমন প্রতিসাম্য কী তৈরি করা, অসামান্য ব্যক্তিগত কী, লবণের মান, সুরক্ষা টোকেন ইত্যাদি etc.
তবে সুরক্ষা-গ্রেডের এলোমেলো সংখ্যাগুলি একটি পৃথক নিবন্ধের মূল্য হিসাবে পৃথক শিল্প।
বেশিরভাগ ক্ষেত্রে সিউডো-র্যান্ডম নম্বর জেনারেটর যথেষ্ট - যেমন বৈজ্ঞানিক সিমুলেশন বা গেমসের জন্য। কিছু ক্ষেত্রে ধারাবাহিকভাবে সংজ্ঞায়িত সিউডো-এলোমেলো ক্রমগুলি এমনকি প্রয়োজনীয় - যেমন গেমগুলিতে প্রচুর ডেটা সঞ্চয় করা এড়াতে আপনি রানটাইমে ঠিক একই মানচিত্র তৈরি করতে বেছে নিতে পারেন।
মূল প্রশ্ন এবং অভিন্ন / অনুরূপ প্রশ্নের (এবং তাদের কাছে অনেকগুলি বিভ্রান্ত "উত্তর") পুনরায় বিতর্কিত ইঙ্গিত দেয় যে ছদ্ম-এলোমেলো সংখ্যার থেকে এলোমেলো সংখ্যাগুলি প্রথম এবং সর্বাধিক গুরুত্বপূর্ণ এবং এটিতে সিউডো-এলোমেলো সংখ্যা ক্রমটি কী তা বোঝা গুরুত্বপূর্ণ প্রথম স্থান এবং এটি বুঝতে যে সিউডো-এলোমেলো নম্বর জেনারেটর আপনি ঠিক তেমন র্যান্ডম নম্বর জেনারেটর ব্যবহার করতে পারেন ঠিক তেমনভাবে ব্যবহৃত হয় না।
স্বজ্ঞাতভাবে আপনি যখন এলোমেলো সংখ্যার জন্য অনুরোধ করবেন - প্রত্যাশিত ফলাফলটি আগের প্রত্যাবর্তিত মানের উপর নির্ভর করে না এবং যদি কেউ এর আগে কিছু অনুরোধ করে এবং কোন মুহুর্তে এবং কোন প্রক্রিয়াতে এবং কোন কম্পিউটারে এবং কোন জেনারেটর থেকে এবং কীসে নির্ভর করে না কী ছায়াপথ এটি অনুরোধ করা হয়েছিল। "এলোমেলো" শব্দের অর্থ কি সর্বোপরি - অনাকাঙ্ক্ষিত এবং যে কোনও কিছুর থেকে স্বতন্ত্র হওয়া - অন্যথায় এটি আর এলোমেলো নয়, তাই না? এই স্বজ্ঞাততার সাথে কোনও সম্ভাব্য প্রসঙ্গে যেমন এলোমেলো নম্বর পেতে কিছু যাদু স্পেসের জন্য ওয়েবে অনুসন্ধান করা স্বাভাবিক natural
^^^ স্বজ্ঞাত প্রত্যাশা ধরনের যে খুব ভুল ও ক্ষতিকর জড়িত সব ক্ষেত্রেই সিউডো-রেণ্ডম নম্বর জেনারেটর সত্য র্যান্ডম সংখ্যার জন্য যুক্তিসংগত থাকা সত্ত্বেও -।
"এলোমেলো সংখ্যা" এর অর্থবহ ধারণাটি বিদ্যমান থাকলেও "সিউডো-এলোমেলো সংখ্যা" বলে কিছুই নেই। একটি সিউডো-র্যান্ডম নম্বর জেনারেটর আসলে ছদ্ম-এলোমেলো সংখ্যা ক্রম উত্পাদন করে ।
বিশেষজ্ঞরা যখন পিআরএনজির মানের কথা বলেন তারা আসলে উত্পন্ন সিকোয়েন্সের পরিসংখ্যানগত বৈশিষ্ট্যগুলি (এবং এর উল্লেখযোগ্য সাব-সিকোয়েন্সগুলি) সম্পর্কে কথা বলেন। উদাহরণস্বরূপ, যদি আপনি দুটি উচ্চ মানের পিআরএনজিগুলিকে ঘুরিয়ে উভয় ব্যবহার করে একত্রিত করেন - আপনি খারাপ ফলাফলের ক্রম তৈরি করতে পারেন - সেগুলি পৃথক পৃথকভাবে ভাল সিকোয়েন্স তৈরি করা সত্ত্বেও (এই দুটি ভাল সিকোয়েন্সগুলি কেবল একে অপরের সাথে সম্পর্কিত হতে পারে এবং এইভাবে খারাপভাবে মিলিত হতে পারে)।
সিউডো-এলোমেলো ক্রম প্রকৃতপক্ষে সর্বদা নির্ণায়ক (এর অ্যালগোরিদম এবং প্রাথমিক পরামিতি দ্বারা পূর্বনির্ধারিত) অর্থাৎ এটি সম্পর্কে এলোমেলোভাবে কিছুই নেই।
সুনির্দিষ্টভাবে rand()
/ srand(s)
জোড়ের জোড়গুলি প্রয়োগ-সংজ্ঞায়িত অ্যালগরিদমের সাথে উত্পন্ন এক-একক প্রতি প্রসেস নন-থ্রেড-সেফ (!) সিউডো-এলোমেলো সংখ্যা ক্রম সরবরাহ করে। ফাংশন rand()
সীমার মান নির্ধারণ করে [0, RAND_MAX]
।
সি 11 স্ট্যান্ডার্ড থেকে উদ্ধৃতি:
srand
ফাংশন সিউডো-রেণ্ডম সংখ্যার একটি নতুন ক্রম পরবর্তী কল দ্বারা ফিরে হওয়ার জন্য একটি বীজ যেমন যুক্তি ব্যবহার rand
। যদি
srand
একই বীজের সাথে ডাকা হয় তবে ছদ্ম-এলোমেলো সংখ্যার ক্রম পুনরাবৃত্তি করা হবে। যদি rand
কোনও কল করার আগে ডাকা হয়, 1 এর বীজ মানের সাথে প্রথমবার srand
যখন srand
ডাকা হয় তখন একই ক্রম তৈরি করা হবে ।
অনেক লোক যুক্তিসঙ্গতভাবে আশা করে যে rand()
এটি অর্ধ-স্বতন্ত্র সমানভাবে বিতরণ সংখ্যার সীমা তৈরি 0
করবে RAND_MAX
। ভাল এটি অবশ্যই স্পষ্টভাবে হওয়া উচিত (অন্যথায় এটি অকেজো) তবে দুর্ভাগ্যক্রমে কেবল স্ট্যান্ডার্ডেরও এটির প্রয়োজন হয় না - এমন কি স্পষ্টত অস্বীকৃতিও রয়েছে যা বলে যে "উত্পাদিত এলোমেলো ক্রমের মান সম্পর্কে কোনও গ্যারান্টি নেই" । কিছু casesতিহাসিক ক্ষেত্রে rand
/ srand
বাস্তবায়ন খুব খারাপ মানের ছিল। যদিও আধুনিক বাস্তবায়নে এটি সম্ভবত যথেষ্ট ভাল - তবে বিশ্বাসটি ভাঙ্গা এবং পুনরুদ্ধার করা সহজ নয়। এর অ-থ্রেড-নিরাপদ প্রকৃতিটি বহু-থ্রেডযুক্ত অ্যাপ্লিকেশনগুলিতে এর নিরাপদ ব্যবহারকে জটিল এবং সীমাবদ্ধ করে তোলে (এখনও সম্ভব - আপনি কেবলমাত্র একটি উত্সর্গীকৃত থ্রেড থেকে এগুলি ব্যবহার করতে পারেন)।
নতুন শ্রেণীর টেম্পলেট std :: mersenne_twister_engine <> (এবং এর সুবিধার্থে টাইপডেফস std::mt19937
/ / std::mt19937_64
ভাল টেম্পলেট প্যারামিটার সংমিশ্রণ সহ) সি -+ 11 স্ট্যান্ডার্ডে সংজ্ঞায়িত প্রতি-বস্তুর সিউডো-এলোমেলো সংখ্যা জেনারেটর সরবরাহ করে। একই টেম্পলেট প্যারামিটার এবং একই সূচনা পরামিতিগুলির সাথে বিভিন্ন বস্তু সি ++ 11 অনুমিত মানক লাইব্রেরি দিয়ে নির্মিত কোনও অ্যাপ্লিকেশনটিতে যে কোনও কম্পিউটারে ঠিক একই-প্রতি-অবজেক্ট আউটপুট ক্রম উত্পন্ন করবে। এই শ্রেণীর সুবিধাটি হ'ল এটির উচ্চমানের আউটপুট ক্রম এবং বাস্তবায়ন জুড়ে সম্পূর্ণ ধারাবাহিকতা।
এছাড়াও আরও অনেক কিছু আছে PRNG ইঞ্জিন সি সংজ্ঞায়িত হয় ++, 11 মানক - এসটিডি :: linear_congruential_engine <> (ঐতিহাসিকভাবে ন্যায্য মানের হিসাবে ব্যবহার srand/rand
এবং কিছু সি মান গ্রন্থাগার বাস্তবায়নের মধ্যে অ্যালগরিদম) এসটিডি :: subtract_with_carry_engine <> । এগুলি প্রতি-বস্তুর আউটপুট ক্রমগুলি পুরোপুরি সংজ্ঞায়িত পরামিতি-নির্ভর gene
আধুনিক দিনের সি ++ 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;
}
পূর্ববর্তী কোডের সংস্করণ যা স্ট্যান্ড :: ইউনিফর্ম_িন্ট_ডিসট্রিবিউশন <> ব্যবহার করে
#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;
}