সি ++ এ এলোমেলো নম্বর কীভাবে তৈরি করবেন?


150

আমি পাশা দিয়ে একটি গেম তৈরি করার চেষ্টা করছি এবং এতে আমার এলোমেলো সংখ্যা থাকা দরকার (ডাইয়ের দিকগুলি অনুকরণ করতে। আমি কীভাবে এটি 1 থেকে 6 এর মধ্যে তৈরি করতে জানি)। ব্যবহার

#include <cstdlib> 
#include <ctime> 
#include <iostream>

using namespace std;

int main() 
{ 
    srand((unsigned)time(0)); 
    int i;
    i = (rand()%6)+1; 
    cout << i << "\n"; 
}

খুব ভাল কাজ করে না, কারণ যখন আমি প্রোগ্রামটি কয়েকবার চালিত করি, তখন আমি আউটপুটটি পাই:

6
1
1
1
1
1
2
2
2
2
5
2

সুতরাং আমি একটি কমান্ড চাই যা প্রতিবার একটি পৃথক এলোমেলো সংখ্যা তৈরি করবে , একের পর এক 5 বার নয়। কোন আদেশ আছে যা এই করবে?


54
বিতরণ বিষয়গুলি একদিকে রাখুন, মনে রাখবেন যে এলোমেলো সংখ্যার সাথে একই ফলাফলটি পরপর কয়েকবার পাওয়ার সম্ভাবনা আসে। আপনি যদি একাধিকবার একই সংখ্যাটি না পাওয়ার নিশ্চয়তা পান তবে ফলাফলগুলি সত্যই এলোমেলো হবে না, তাই না?
cdowie

5
আপনি কী ভাবছেন যে এই সংখ্যাগুলি এলোমেলো নয়? বাস্তবের জন্য একটি ডাই ছুড়ে দিন এবং আপনি খুব ভালভাবে এই ফলাফলটি পেতে পারেন। যদি তাদের প্রতিটি থ্রোয়ের মধ্যে আলাদা হওয়ার গ্যারান্টিযুক্ত হয় তবে এটি আসলে এলোমেলো হবে না।
ম্যাটজগ্লোলোয়

2
এছাড়াও পড়া eternallyconfuzzled.com/arts/jsw_art_rand.aspx কেন মডুলাস অপারেটর ব্যবহার প্রায়ই একটি ভাল ধারণা নয়।
বেনিয়ামিন ব্যানিয়ার

4
আপনি একটি মন্তব্য বা এমনকি একটি উত্তর ফিট করতে পারেন তার চেয়ে অনেক বেশি ভুল বোঝাবুঝি। আপনাকে সিউডো-এলোমেলো সংখ্যা জেনারেটর সম্পর্কে, বীজ সম্পর্কে, সত্যিকারের এলোমেলো বীজ বাছাইয়ের গুরুত্ব এবং অভিন্ন বিতরণ সম্পর্কে স্বাধীনভাবে শিখতে হবে।
কেরেক এসবি

20
আপনি সময় সঙ্গে বীজ যখন। এর অর্থ হ'ল আপনি যদি আপনার প্রোগ্রামটি সেকেন্ডে একবারের বেশি চালান তবে আপনি একই নম্বর পাবেন।
মার্টিন ইয়র্ক

উত্তর:


79

আপনার পরীক্ষার আবেদনের সর্বাধিক মৌলিক সমস্যাটি হ'ল আপনি 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;
}

আমি এখানে লিঙ্কে অনুরূপ প্রশ্ন জিজ্ঞাসা করেছি তবে এখনও কোনও পরিষ্কার উত্তর খুঁজে পাইনি। আপনি কি দয়া করে এটি প্রমাণ করতে পারেন যে "আসলে আপনার একবারে srand (বীজ) কল করা উচিত এবং তারপরে কোডগুলি দিয়ে র্যান্ড ()" কল করুন কারণ আপনি ইতিমধ্যে যা বলেছেন তা আমি ইতিমধ্যে করেছি তবে এটি সঠিকভাবে কাজ করছে না।
বাশবুরাক

2
@ বাশবুরাক দেখে মনে হচ্ছে আপনি এই উত্তরের বিষয়টি পুরোপুরি মিস করেছেন। আপনি আমার উদ্ধৃতিটি ঠিক কেন কাটলেন? আমি আমার উত্তরে আক্ষরিকভাবে বলেছিলাম "আসলে আপনার একবারে শ্রান্ড (বীজ) কল করা উচিত এবং তারপরে র্যান্ড () কে বহুবার কল করা উচিত এবং সেই ক্রমটি বিশ্লেষণ করুন - এটি এলোমেলো হওয়া উচিত should" আপনি কি লক্ষ্য করেছেন যে একক srand (...) কল করার পরে আপনার র‌্যান্ড () অনেক সময় বলা উচিত? আপনার লিঙ্কে আপনার প্রশ্নটি ঠিক একই ভুল বোঝাবুঝি সহ এই প্রশ্নের সঠিক সদৃশ d
সার্জ ডুন্ডিচ

এটি একটি পুরানো উত্তর, তবে আপনি যখন "সি ++ র্যান্ডম নম্বর জেনারেশন" গুগল করেন তখন তা প্রদর্শিত হবে। কারণ এটি আপনি ব্যবহার উপদেশ এটা সি ++ প্রোগ্রামারদের জন্য দরিদ্র উপদেশ rand()এবং srand()। আপনি এটি আপডেট করতে পারেন?
ইয়াক্ক - অ্যাডাম নেভ্রামাউন্ট

@ ইয়াক্ক-অ্যাডামনেভারামোঁ এটি আসলে ব্যবহার করার পরামর্শ দেয় না rand()এবং srand()। বাস্তবে এটি কেবল প্রদত্ত বিবরণ দিয়ে প্রশ্নের উত্তর দেয়। সিউডো-এলোমেলো সংখ্যার প্রজন্মের মৌলিক ধারণাগুলি ব্যাখ্যা করা উচিত - সিউডো-এলোমেলো ক্রম এবং এর বীজের একেবারে অর্থের মতো - এটি বর্ণনার (যা ব্যবহার করে rand/ srand) থেকে স্পষ্ট হয় । আমি ঠিক এটি করার চেষ্টা করছি এবং সবচেয়ে সহজ এবং পরিচিত rand/ srandসংমিশ্রণটি ব্যবহার করব। মজার বিষয় হ'ল আরও কিছু উত্তর - এমনকি খুব বড় রেটিং সহও - প্রশ্নের লেখকের মতো একই ভুল বোঝাবুঝিতে ভুগছে।
সার্জ ডুন্ডিচ

@ ইয়াক্ক-অ্যাডামনেভ্র্যামন্ট আমি আপনার পরামর্শ গ্রহণ করেছি এবং আমার উত্তরটি নতুন সি ++ সংযোজন সম্পর্কিত কিছু তথ্যের সাথে সংশোধন করেছি। যদিও আমি এই বিষয়ে বন্ধ একটু বিবেচনা - কিন্তু আপনার পরামর্শের পাশাপাশি অন্য কিছু উত্তর ইঙ্গিত করে যে উভয় ভাল পুরানো std::rand/std::srandএবং নতুন সি ++ লাইব্রেরি বৈশিষ্ট্যগুলির মতো std::random_device<>, এসটিডি :: mersenne_twister_engine <> এবং বৃন্দ র্যান্ডম ডিস্ট্রিবিউশন কিছু ব্যাখ্যা প্রয়োজন।
সার্জ ডুন্ডিচ

214

Modulo ব্যবহার এলোমেলো সংখ্যা জেনারেটরের উপর নির্ভর করে এলোমেলো সংখ্যায় পক্ষপাতের পরিচয় দিতে পারে। আরও তথ্যের জন্য এই প্রশ্নটি দেখুন। অবশ্যই, একটি এলোমেলো ক্রমতে পুনরাবৃত্তি সংখ্যাগুলি পাওয়া পুরোপুরি সম্ভব।

উন্নত বিতরণের জন্য কিছু সি ++ 11 বৈশিষ্ট্য ব্যবহার করে দেখুন:

#include <random>
#include <iostream>

int main()
{
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]

    std::cout << dist6(rng) << std::endl;
}

সি ++ 11 র্যান্ডম সংখ্যার আরও তথ্যের জন্য এই প্রশ্ন / উত্তরটি দেখুন। উপরেরগুলি এটি করার একমাত্র উপায় নয়, তবে এটি একটি উপায়।


7
ব্যবহারের মাধ্যমে প্রবর্তনের পক্ষপাতের পরিমাণটি %6অদৃশ্যভাবে কম। আপনি যদি লাস ভেগাসে ব্যবহারের জন্য একটি ক্রেপস গেমটি লিখছেন তবে অন্য কোনও প্রসঙ্গে কোনও ফল না পেয়ে তাৎপর্যপূর্ণ।
হট লিকস

9
হটলিক্স: সম্মত, তবে আপনি যদি সি ++ এর এমন একটি সংস্করণ ব্যবহার করেন যা সমর্থন করে random_deviceএবং mt19937ইতিমধ্যে, তবে আক্ষরিক অর্থে কোনও কারণ খুঁজে পাওয়া যায় না এবং স্ট্যান্ডার্ডটিও ব্যবহার করা উচিত uniform_int_distributionনয়।
কুইকসপ্লসোন

4
সমস্ত প্রোগ্রামারদের লোককে প্লেগের মতো মডুলো এড়াতে পরামর্শ দেওয়া উচিত কারণ এটি বিভাগ ব্যবহার করে এবং এতে কয়েকশ ঘড়ির চক্র ব্যয় হয় এবং আপনার অ্যাপ্লিকেশন সময়টি গোলমাল করতে পারে এবং / বা প্রচুর ব্যাটারি শক্তি পোড়াতে পারে।

3
"রেঞ্জ" এর জন্য কি আরএনজি?
ক্রিস্টোফার

4
@ ChristofferHjärtström: এটা জন্য andom এন আমভের enerator।
কর্নস্টালক

11

আপনি যদি বুস্ট লিব ব্যবহার করেন তবে আপনি এলোমেলোভাবে জেনারেটরটি পেতে পারেন:

#include <iostream>
#include <string>

// Used in randomization
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>

using namespace std;
using namespace boost;

int current_time_nanoseconds(){
    struct timespec tm;
    clock_gettime(CLOCK_REALTIME, &tm);
    return tm.tv_nsec;
}

int main (int argc, char* argv[]) {
    unsigned int dice_rolls = 12;
    random::mt19937 rng(current_time_nanoseconds());
    random::uniform_int_distribution<> six(1,6);

    for(unsigned int i=0; i<dice_rolls; i++){
        cout << six(rng) << endl;
    }
}

যেখানে ফাংশনটি current_time_nanoseconds()ন্যানোসেকেন্ডগুলিতে বর্তমান সময় দেয় যা বীজ হিসাবে ব্যবহৃত হয়।


এলোমেলো পূর্ণসংখ্যা এবং একটি তারিখে তারিখ পেতে এখানে আরও সাধারণ শ্রেণি রয়েছে:

#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"


using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;


class Randomizer {
private:
    static const bool debug_mode = false;
    random::mt19937 rng_;

    // The private constructor so that the user can not directly instantiate
    Randomizer() {
        if(debug_mode==true){
            this->rng_ = random::mt19937();
        }else{
            this->rng_ = random::mt19937(current_time_nanoseconds());
        }
    };

    int current_time_nanoseconds(){
        struct timespec tm;
        clock_gettime(CLOCK_REALTIME, &tm);
        return tm.tv_nsec;
    }

    // C++ 03
    // ========
    // Dont forget to declare these two. You want to make sure they
    // are unacceptable otherwise you may accidentally get copies of
    // your singleton appearing.
    Randomizer(Randomizer const&);     // Don't Implement
    void operator=(Randomizer const&); // Don't implement

public:
    static Randomizer& get_instance(){
        // The only instance of the class is created at the first call get_instance ()
        // and will be destroyed only when the program exits
        static Randomizer instance;
        return instance;
    }
    bool method() { return true; };

    int rand(unsigned int floor, unsigned int ceil){
        random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
        return (rand_(rng_));
    }

    // Is not considering the millisecons
    time_duration rand_time_duration(){
        boost::posix_time::time_duration floor(0, 0, 0, 0);
        boost::posix_time::time_duration ceil(23, 59, 59, 0);
        unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
        return seconds(rand_seconds);
    }


    date rand_date_from_epoch_to_now(){
        date now = second_clock::local_time().date();
        return rand_date_from_epoch_to_ceil(now);
    }

    date rand_date_from_epoch_to_ceil(date ceil_date){
        date epoch = ptime(date(1970,1,1)).date();
        return rand_date_in_interval(epoch, ceil_date);
    }

    date rand_date_in_interval(date floor_date, date ceil_date){
        return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
    }

    ptime rand_ptime_from_epoch_to_now(){
        ptime now = second_clock::local_time();
        return rand_ptime_from_epoch_to_ceil(now);
    }

    ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
        ptime epoch = ptime(date(1970,1,1));
        return rand_ptime_in_interval(epoch, ceil_date);
    }

    ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
        time_duration const diff = ceil_date - floor_date;
        long long gap_seconds = diff.total_seconds();
        long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
        return floor_date + seconds(step_seconds);
    }
};

1
এখন যেহেতু স্ট্যান্ডার্ডের অংশ হিসাবে আমাদের এলোমেলোভাবে রয়েছে আমি যদি আপনি সত্যিকারের পুরানো সংকলক না ব্যবহার করেন তবে আমি বুস্ট সংস্করণটি ব্যবহার করতে নিরুৎসাহিত করব।
মার্টিন ইয়র্ক

9
#include <iostream>
#include <cstdlib>
#include <ctime>

int main() {
    srand(time(NULL));
    int random_number = std::rand(); // rand() return a number between ​0​ and RAND_MAX
    std::cout << random_number;
    return 0;
}

http://en.cppreference.com/w/cpp/numeric/random/rand


প্রশ্ন লেখকের কোডের সাথে পার্থক্য কী? (আপনি ব্যবহার না করেন তা বাদে %6)) এবং আপনি যদি সি লাইব্রেরির ফাংশনের std::randসি ++ এপিআই ব্যবহার করার সিদ্ধান্ত নিয়েছেন randতবে কেন ব্যবহার করবেন না std::timeএবং std::srandসি ++ স্টাইলের ধারাবাহিকতার জন্য?
সার্জ ডুন্ডিচ

4

Randomerএখান থেকে এলোমেলো সংখ্যা তৈরির জন্য পূর্ণ শ্রেণীর কোড পেতে পারেন !

যদি আপনার প্রকল্পের বিভিন্ন অংশে এলোমেলো সংখ্যার প্রয়োজন হয় তবে আপনি এর ভিতরে Randomerথাকা সমস্ত স্ট্যাপকে আলাদা করতে একটি পৃথক শ্রেণি তৈরি করতে পারেন random

এরকম কিছু:

class Randomer {
    // random seed by default
    std::mt19937 gen_;
    std::uniform_int_distribution<size_t> dist_;

public:
    /*  ... some convenient ctors ... */ 

    Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
        : gen_{seed}, dist_{min, max} {
    }

    // if you want predictable numbers
    void SetSeed(unsigned int seed) {
        gen_.seed(seed);
    }

    size_t operator()() {
        return dist_(gen_);
    }
};

এই ধরণের শ্রেণি পরবর্তী সময়ে কার্যকর হবে:

int main() {
    Randomer randomer{0, 10};
    std::cout << randomer() << "\n";
}

উদাহরণস্বরূপ আপনি এই লিঙ্কটি চেক করতে পারেন যে আমি এ জাতীয় Randomerক্লাসটি এলোমেলো স্ট্রিং উত্পন্ন করতে কীভাবে ব্যবহার করি । আপনি Randomerইচ্ছা করলেও ব্যবহার করতে পারেন।


আপনি কি আপনার সমস্ত র্যান্ডোমার অবজেক্টের জন্য পুনরায় জেনারেটরটি ব্যবহার করতে চান না? বিশেষত যেহেতু এটি আরম্ভ করা এবং তার রাজ্য বজায় রাখা তুলনামূলকভাবে ব্যয়বহুল।
মার্টিন ইয়র্ক

3

প্রতিবার আলাদা এলোমেলো সংখ্যা তৈরি করুন, একের পর এক ছয় বার নয়।

কেস দৃশ্যের ব্যবহার

আমি অনুমানের সমস্যাটিকে ছয় বিটের কাগজের একটি ব্যাগের সাথে তুলনা করেছি, যার প্রতিটির উপরে 0 থেকে 5 পর্যন্ত মূল্য লেখা আছে। ব্যাগ থেকে প্রতিবার একটি নতুন টুকরো টুকরো টুকরো টুকরো টানা হয়। যদি ব্যাগটি খালি থাকে, তবে নম্বরগুলি ব্যাগে রেখে দেওয়া হবে।

... এটি থেকে, আমি বিভিন্ন ধরণের অ্যালগোরিদম তৈরি করতে পারি।

অ্যালগরিদম

একটি ব্যাগ সাধারণত ক Collection। আমি bool[]ব্যাগের ভূমিকা নিতে একটি (অন্যথায় বুলিয়ান অ্যারে, বিট প্লেন বা বিট ম্যাপ হিসাবে পরিচিত) বেছে নিয়েছি ।

আমি যে কারণটি বেছে নিয়েছি bool[]তা হ'ল প্রতিটি আইটেমের সূচি ইতিমধ্যে প্রতিটি কাগজের প্রতিটি টুকরোর মান। যদি কাগজপত্রগুলিতে সেগুলিতে অন্য কিছু লেখা থাকে তবে আমি Dictionary<string, bool>তার জায়গায় একটি ব্যবহার করতে পারতাম । বুলিয়ান মানটি এখনও অঙ্কিত হয়েছে কিনা তা ট্র্যাক রাখতে ব্যবহার করা হয়।

এলোমেলো সংখ্যা নির্বাচন করা হিসাবে নামক একটি কাউন্টার সেই গণনাটিকে RemainingNumberCountসূচনা করা 5হয়। এটি প্রতিবার নতুন সংখ্যা আঁকতে চাইলে কতগুলি কাগজের টুকরো রেখে গেছে তা গণনা করা থেকে আমাদের বাঁচায়।

পরবর্তী র্যান্ডম মান আমি ব্যবহার করছি নির্বাচন করতে for..loopবন্ধ গণনা যখন একটি ইনডেক্স ব্যাগ, এবং একটি পাল্টা মাধ্যমে স্ক্যান করতে indexহয় falseনামক NumberOfMoves

NumberOfMovesপরবর্তী উপলব্ধ নম্বর চয়ন করতে ব্যবহৃত হয়। NumberOfMovesপ্রথমে 0এবং এর মধ্যে একটি এলোমেলো মান হিসাবে সেট করা হয় 5, কারণ 0-5 উপলভ্য পদক্ষেপগুলি আমরা ব্যাগের মাধ্যমে করতে পারি। উপর পরবর্তী পুনরাবৃত্তিতে NumberOfMovesমধ্যে একটি র্যান্ডম মান হতে সেট করা হয় 0এবং 4কারণ এখন 0..4 পদক্ষেপ আমরা ব্যাগ মাধ্যমে দিতে পারে। যেহেতু সংখ্যা ব্যবহৃত হয়, উপলভ্য সংখ্যাগুলি হ্রাস হয় তাই আমরা পরিবর্তে rand() % (RemainingNumberCount + 1)পরবর্তী মান গণনা করতে ব্যবহার করি NumberOfMoves

যখন NumberOfMovesকাউন্টার শূন্যে পৌঁছে যায়, নিম্নলিখিতগুলি for..loopউচিত:

  1. বর্তমান for..loopমানটিকে সূচক হিসাবে একই হিসাবে সেট করুন ।
  2. ব্যাগে সমস্ত নম্বর সেট করুন false
  3. থেকে বিরতি for..loop

কোড

উপরের সমাধানের কোডটি নিম্নরূপ:

(একের পর এক মূল .cpp ফাইলে নিম্নলিখিত তিনটি ব্লক রেখে দিন)

#include "stdafx.h"
#include <ctime> 
#include <iostream>
#include <string>

class RandomBag {
public:
    int Value = -1;

    RandomBag() {
        ResetBag();

    }

    void NextValue() {
        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        int NumberOfMoves = rand() % (RemainingNumberCount + 1);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            if (BagOfNumbers[i] == 0) {
                NumberOfMoves--;

                if (NumberOfMoves == -1)
                {
                    Value = i;

                    BagOfNumbers[i] = 1;

                    break;

                }

            }



        if (RemainingNumberCount == 0) {
            RemainingNumberCount = 5;

            ResetBag();

        }
        else            
            RemainingNumberCount--; 

    }

    std::string ToString() {
        return std::to_string(Value);

    }

private:
    bool BagOfNumbers[6]; 

    int RemainingNumberCount;

    int NumberOfMoves;

    void ResetBag() {
        RemainingNumberCount = 5;

        NumberOfMoves = rand() % 6;

        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            BagOfNumbers[i] = 0;

    }

};

একটি কনসোল ক্লাস

আমি এই কনসোল ক্লাসটি তৈরি করেছি কারণ এটি আউটপুটটিকে পুনর্নির্দেশ করা সহজ করে।

কোডের নীচে ...

Console::WriteLine("The next value is " + randomBag.ToString());

... দ্বারা প্রতিস্থাপন করা যেতে পারে ...

std::cout << "The next value is " + randomBag.ToString() << std::endl; 

... এবং তারপরে এই Consoleক্লাসটি মুছে ফেলা যেতে পারে।

class Console {
public:
    static void WriteLine(std::string s) {
        std::cout << s << std::endl;

    }

};

প্রধান পদ্ধতি

নীচে ব্যবহারের উদাহরণ:

int main() {
    srand((unsigned)time(0)); // Initialise random seed based on current time

    RandomBag randomBag;

    Console::WriteLine("First set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nSecond set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nThird set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nProcess complete.\n");

    system("pause");

}

উদাহরণ আউটপুট

আমি যখন প্রোগ্রামটি চালিয়েছি, আমি নিম্নলিখিত ফলাফলটি পেয়েছি:

First set of six...

The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1

Second set of six...

The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5

Third set of six...

The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1

Process complete.

Press any key to continue . . .

শেষ বিবৃতি

এই প্রোগ্রামটি ভিজ্যুয়াল স্টুডিও 2017 ব্যবহার করে লেখা হয়েছিল এবং আমি এটি Visual C++ Windows Console Applicationব্যবহার করে একটি প্রকল্প তৈরি করতে বেছে নিয়েছি .Net 4.6.1

আমি এখানে বিশেষভাবে কিছু করছি না, সুতরাং কোডটি ভিজ্যুয়াল স্টুডিওর পূর্ববর্তী সংস্করণগুলিতেও কাজ করা উচিত।


যদি এটি ভিএস 2017 হয় তবে আপনি স্ট্যান্ডার্ড লাইব্রেরির সর্বশেষ সংস্করণটি ব্যবহার করা উচিত: en.cppreferences.com/w/cpp/numeric/random । বর্তমানে এই উদাহরণটি সি র্যান্ডম গ্রন্থাগার ফাংশন ব্যবহার করে এবং "উত্পাদিত এলোমেলো ক্রমের মান সম্পর্কে কোনও গ্যারান্টি নেই"।
রবার্ট আন্দ্রেজুক

3

আপনি যখনই random number generationসি ++ প্রোগ্রামিং ল্যাঙ্গুয়েজে কোনও বেসিক ওয়েব অনুসন্ধান করেন তখন এই প্রশ্নটি সাধারণত পপ আপ হয়! আমি ভবিষ্যতে কোডারদের জন্য সি ++ তে সিউডো-এলোমেলো সংখ্যা জেনারেশনের ধারণাটি আরও ভালভাবে স্পষ্ট করতে আমার টুপিটি রিংয়ে ফেলে দিতে চাই যা অনিবার্যভাবে ওয়েবে এই একই প্রশ্নটি অনুসন্ধান করবে!

অধিকার

সিউডো-এলোমেলো সংখ্যা জেনারেশনে একটি নির্ধারক অ্যালগরিদম ব্যবহারের প্রক্রিয়া জড়িত যা সংখ্যার ক্রম উত্পাদন করে যার বৈশিষ্ট্যগুলি প্রায় এলোমেলো সংখ্যার অনুরূপ । আমি বলছি আনুমানিক অনুরূপ , কারণ সত্যিকারের এলোমেলোতা গণিত এবং কম্পিউটার বিজ্ঞানের ক্ষেত্রে বরং এক অধরা রহস্য । সুতরাং, সিউডো-এলোমেলো শব্দটি কেন অধিক প্যাডেন্টালি সঠিকভাবে ব্যবহৃত হয়েছে!

আপনি আসলে পিআরএনজি ব্যবহার করার আগে, অর্থাত্ pseudo-random number generatorআপনাকে অবশ্যই একটি প্রাথমিক মান সহ অ্যালগরিদম সরবরাহ করতে হবে যা প্রায়শই বীজ হিসাবে উল্লেখ করা হয় । তবে বীজটি নিজেই অ্যালগরিদম ব্যবহারের আগে একবার সেট করতে হবে!

/// Proper way!
seed( 1234 ) /// Seed set only once...
for( x in range( 0, 10) ):
  PRNG( seed ) /// Will work as expected

/// Wrong way!
for( x in rang( 0, 10 ) ):
  seed( 1234 ) /// Seed reset for ten iterations!
  PRNG( seed ) /// Output will be the same...

সুতরাং, আপনি যদি সংখ্যার একটি ভাল ক্রম চান, তবে আপনাকে অবশ্যই পিআরএনজিতে পর্যাপ্ত বীজ সরবরাহ করতে হবে!

ওল্ড সি ওয়ে

সি ++ এর পিছনের সামঞ্জস্যপূর্ণ স্ট্যান্ডার্ড লাইব্রেরিটি শিরোনাম ফাইলে পাওয়া লিনিয়ার কংগ্রুভেন্সি জেনারেটর বলে যা ব্যবহার করে cstdlib! এই পিআরএনজি একটি বিচ্ছিন্ন পিসওয়াস ফাংশনের মাধ্যমে কাজ করে যা মডিউলার গাণিতিক ব্যবহার করে, অর্থাত্ একটি দ্রুত অ্যালগরিদম যা ব্যবহার করতে পছন্দ করে modulo operator '%'। নীচে এই পিআরএনজি এর সাধারণ ব্যবহার, @ অনুমানের জিজ্ঞাসা করা মূল প্রশ্নের সাথে সম্পর্কিত:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main( void )
{
  int low_dist  = 1;
  int high_dist = 6;
  std::srand( ( unsigned int )std::time( nullptr ) );
  for( int repetition = 0; repetition < 10; ++repetition )
    std::cout << low_dist + std::rand() % ( high_dist - low_dist ) << std::endl;
  return 0;
}

সি এর পিআরএনজি এর সাধারণ ব্যবহারে ইস্যুগুলির পুরো হোস্ট থাকে:

  1. std::rand()প্রদত্ত পরিসরের মধ্যে সিউডো-এলোমেলো সংখ্যার যথাযথ উত্পন্নকরণের সামগ্রিক ইন্টারফেসটি খুব স্বজ্ঞাত নয়, উদাহরণস্বরূপ, @ অনুমানযোগ্যতাটি যেভাবে চেয়েছিল তার মধ্যে [1, 6] এর মধ্যে সংখ্যা উত্পাদন করছে।
  2. পিগনহোল নীতিমালার কারণে সাধারণ ব্যবহার সিউডো-এলোমেলো সংখ্যার অভিন্ন বিতরণেরstd::rand() সম্ভাবনা দূর করে ।
  3. প্রযুক্তিগতভাবে সাধারণ পদ্ধতিতে std::rand()বদ্ধমূল হওয়া std::srand( ( unsigned int )std::time( nullptr ) )সঠিক নয়, কারণ time_tএটি একটি সীমাবদ্ধ প্রকার হিসাবে বিবেচিত হয় । অতএব, থেকে রুপান্তরের time_tজন্য unsigned int নিশ্চিত করা হয় না!

সি এর পিআরএনজি ব্যবহারের সামগ্রিক সমস্যাগুলি সম্পর্কে এবং আরও কীভাবে তাদের উদ্ভব করতে পারে সে সম্পর্কে আরও বিশদ তথ্যের জন্য দয়া করে র্যান্ড () (সি / সি ++) ব্যবহার করে দেখুন: সি স্ট্যান্ডার্ড লাইব্রেরির র্যান্ড () ফাংশনটির জন্য পরামর্শ !

স্ট্যান্ডার্ড সি ++ ওয়ে

আইএসও / আইইসি 14882: 2011 স্ট্যান্ডার্ড প্রকাশিত হওয়ার পরে, সি ++ 11 প্রকাশিত হওয়ার পরে, randomগ্রন্থাগারটি কিছু সময়ের জন্য সি ++ প্রোগ্রামিং ভাষার বাইরে রয়েছে। এই গ্রন্থাগারটি একাধিক পিআরএনজি এবং বিভিন্ন বিতরণ প্রকার যেমন: অভিন্ন বন্টন , সাধারণ বিতরণ , দ্বিপদী বিতরণ ইত্যাদিতে সজ্জিত রয়েছে নীচের উত্স কোড উদাহরণটি random@ অনুমানের মূল প্রশ্নের সাথে সম্পর্কিত লাইব্রেরির একটি খুব মৌলিক ব্যবহার দেখায় :

#include <iostream>
#include <cctype>
#include <random>

using u32    = uint_least32_t; 
using engine = std::mt19937;

int main( void )
{
  std::random_device os_seed;
  const u32 seed = os_seed();

  engine generator( seed );
  std::uniform_int_distribution< u32 > distribute( 1, 6 );

  for( int repetition = 0; repetition < 10; ++repetition )
    std::cout << distribute( generator ) << std::endl;
  return 0;
}

32 বিট Mersenne প্রতারক ইঞ্জিন, একটি সঙ্গে অভিন্ন বন্টন এর পূর্ণসংখ্যা মান উপরোক্ত উদাহরণে কাজে লাগিয়ে যায়নি। (উত্স কোডে ইঞ্জিনটির নামটি অদ্ভুত শোনায়, কারণ এটির নামটি 2 ^ 19937-1 এর সময়কাল থেকে আসে )। উদাহরণটি std::random_deviceইঞ্জিন বীজ করার জন্যও ব্যবহার করে, যা অপারেটিং সিস্টেম থেকে এর মান অর্জন করে (যদি আপনি লিনাক্স সিস্টেম ব্যবহার করে থাকেন তবে এর std::random_deviceথেকে একটি মান ফেরত দেয় /dev/urandom)।

খেয়াল করুন, আপনার কোনও ইঞ্জিনstd::random_device বীজ করতে হবে না । আপনি ধ্রুবক বা এমনকি লাইব্রেরি ব্যবহার করতে পারেন ! আপনাকে ইঞ্জিনের 32-বিট সংস্করণও ব্যবহার করতে হবে না , অন্যান্য বিকল্প রয়েছে ! গ্রন্থাগারের সক্ষমতা সম্পর্কে আরও তথ্যের জন্য , দয়া করে cplusplus.com দেখুনchronostd::mt19937random

সব মিলিয়ে, সি ++ প্রোগ্রামারগুলিকে std::rand()আর ব্যবহার করা উচিত নয় , এটি খারাপ কারণ নয় , তবে বর্তমান মানটি আরও ভাল বিকল্প প্রদান করে যা আরও সোজা এগিয়ে এবং নির্ভরযোগ্য । আশা করি, আপনারা অনেকেই এটি সহায়ক বলে মনে করেন, বিশেষত আপনারা যারা সম্প্রতি ওয়েব অনুসন্ধান করেছেন generating random numbers in c++!


2

এখানে একটি সমাধান। এমন একটি ফাংশন তৈরি করুন যা এলোমেলো নম্বর দেয় এবং এটি বিশ্বব্যাপী করতে মূল ফাংশনের বাইরে রাখে। আশাকরি এটা সাহায্য করবে

#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
    srand((unsigned)time(0));
    int die1;
    int die2;
    for (int n=10; n>0; n--){
    die1 = rollDie();
    die2 = rollDie();
    cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
    return (rand()%6)+1;
}

2

এই কোড থেকে র্যান্ডম সংখ্যা উৎপন্ন nকরতে m

int random(int from, int to){
    return rand() % (to - from + 1) + from;
}

উদাহরণ:

int main(){
    srand(time(0));
    cout << random(0, 99) << "\n";
}

2
এটি আসলে প্রশ্নের উত্তর দেয় না।
হলিব্ল্যাকগ্যাট

1
আপনি এটি ঠিক করেন নি। প্রশ্নের মূল বিষয় হ'ল আপনি যদি প্রতি সেকেন্ডে একাধিকবার প্রোগ্রামটি চালান, তবে এটি একই র্যান্ডম মানগুলি উত্পন্ন করে। আপনার কোডও তা করে।
হলিব্ল্যাকগ্যাট

1
@ হোলিব্ল্যাকগেট আমি একাধিক রানের জন্য এটি পরীক্ষা করেছি, এটি কাজ করছে। আপনি কি এর srand(time(0))আগে মূল কার্যক্রমে যুক্ত করেছেন random(n, m)?
আমির ফো

1
আপনি যোগ করা উচিত srand(time(0))লুপ জন্য অথবা ফাংশন বাস্তবায়ন ভিতরে প্রধান ফাংশন না।
আমির ফো

1
আমি আপনার কোড ভারব্যাটিম কপি করেছি। আপনি কি প্রতি সেকেন্ডে একাধিকবার এটি চালিয়েছেন ?
হলি ব্ল্যাককিট

1

প্রতিটি রুন ফাইলের জন্য এলোমেলোভাবে

size_t randomGenerator(size_t min, size_t max) {
    std::mt19937 rng;
    rng.seed(std::random_device()());
    //rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);

    return dist(rng);
}

1
আপনার একাধিকবার জেনারেটর তৈরি করার কথা নয়। এটি একগুচ্ছ রাজ্য বজায় রাখে যাতে এটি এলোমেলো সংখ্যার ক্রম উত্পন্ন করে যাতে উপযুক্ত বিতরণ হয় (এলোমেলো দেখানোর জন্য)।
মার্টিন ইয়র্ক

-2

এখানে প্রায় একটি সাধারণ র্যান্ডম জেনারেটর। 0: এর আশপাশে ইতিবাচক এবং নেতিবাচক মান উত্পন্ন করার সমান সম্ভাবনা

  int getNextRandom(const size_t lim) 
  {
        int nextRand = rand() % lim;
        int nextSign = rand() % lim;
        if (nextSign < lim / 2)
            return -nextRand;
        return nextRand;
  }


   int main()
   {
        srand(time(NULL));
        int r = getNextRandom(100);
        cout << r << endl;
        return 0;
   }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.