<random> লিনাক্সে একই সংখ্যা উত্পন্ন করে তবে উইন্ডোজে নয়


91

নীচের কোডটি অন্তর্ভুক্ত [1,100] পাঁচটি সিউডো-এলোমেলো সংখ্যার একটি তালিকা উত্পন্ন করার জন্য বোঝানো হয়েছে। আমি এর default_random_engineসাথে বীজ বন্টন করি time(0), যা ইউনিক্স সময়ে সিস্টেমের সময় দেয় । আমি যখন মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও 2013 ব্যবহার করে উইন্ডোজ 7 এ এই প্রোগ্রামটি সংকলন ও পরিচালনা করি তখন এটি প্রত্যাশার মতো কাজ করে (নীচে দেখুন)। আমি যখন আর + লিনাক্সে জি ++ সংকলক সহ এটি করি, তবে এটি অদ্ভুতভাবে আচরণ করে।

লিনাক্সে, প্রতিবার 5 টি সংখ্যা তৈরি করা হবে। সর্বশেষ 4 নম্বর প্রতিটি মৃত্যুদন্ডের ক্ষেত্রে পৃথক হবে (যেমনটি প্রায়শই হবে) তবে প্রথম সংখ্যাটি একই থাকবে।

উইন্ডোজ এবং লিনাক্সে 5 টি মৃত্যুদন্ড কার্যকর করা ফলাফল:

      | Windows:       | Linux:        
---------------------------------------
Run 1 | 54,01,91,73,68 | 25,38,40,42,21
Run 2 | 46,24,16,93,82 | 25,78,66,80,81
Run 3 | 86,36,33,63,05 | 25,17,93,17,40
Run 4 | 75,79,66,23,84 | 25,70,95,01,54
Run 5 | 64,36,32,44,85 | 25,09,22,38,13

রহস্য যোগ করার সাথে সাথে, সেই প্রথম সংখ্যাটি পর্যায়ক্রমে লিনাক্সে একজনের দ্বারা বাড়ানো হয়। উপরের ফলাফলগুলি প্রাপ্ত করার পরে, আমি প্রায় 30 মিনিট অপেক্ষা করে আবার চেষ্টা করেছি যে 1 ম সংখ্যাটি পরিবর্তিত হয়েছে এবং এখন সর্বদা 26 হিসাবে উত্পন্ন হয় It এর পরিবর্তিত মান সহ time(0)

কেন প্রথম সংখ্যাটি খুব কমই রান জুড়ে পরিবর্তিত হয়, এবং তারপরে এটি যখন 1 দ্বারা বৃদ্ধি হয়?

কোড. এটি পরিষ্কারভাবে 5 টি সংখ্যা এবং সিস্টেমের সময় মুদ্রণ করে:

#include <iostream>
#include <random>
#include <time.h>

using namespace std;

int main()
{
    const int upper_bound = 100;
    const int lower_bound = 1;

    time_t system_time = time(0);    

    default_random_engine e(system_time);
    uniform_int_distribution<int> u(lower_bound, upper_bound);

    cout << '#' << '\t' << "system time" << endl
         << "-------------------" << endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);
        cout << secret << '\t' << system_time << endl;
    }   

    system("pause");
    return 0;
}

4
sizeof(time_t)বনাম কী sizeof(default_random_engine::result_type)?
মার্ক র্যানসম

4
default_random_engineএই দুটি প্ল্যাটফর্মের সাথে নোটটি সম্পূর্ণ আলাদা।
টিসি

4
এটি এখনও এলোমেলো বিটিডাব্লু হতে পারে।
আলেক টিল

4
প্রতিটি প্রোগ্রামার কি এমন এক পর্যায়ে চলে যায় যেখানে তারা মনে করে যে সময়টি একটি ভাল এলোমেলো সংখ্যার জেনারেটর বীজ?
ल्डফার্ট

6
@ ওল্ডফার্ট হ্যাঁ, একে একাডেমিয়া বলা হয়।
কেসি

উত্তর:


141

যা চলছে তা এখানে:

  • default_random_engineইন লিবিস্টডিসি ++ (জিসিসির স্ট্যান্ডার্ড লাইব্রেরি) minstd_rand0, যা একটি সাধারণ লিনিয়ার কংগ্রেসনাল ইঞ্জিন:

    typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
    
  • এই ইঞ্জিনটি যেভাবে এলোমেলো সংখ্যা তৈরি করে তা হ'ল x i + 1 = (16807x i + 0) মোড 2147483647 ।

  • সুতরাং, যদি বীজ 1 দ্বারা পৃথক হয়, তবে বেশিরভাগ সময় প্রথম উত্পন্ন সংখ্যাটি 16807 দ্বারা পৃথক হবে।

  • এই জেনারেটরের ব্যাপ্তি [1, 2147483646]। যেভাবে libstdc ++ এর uniform_int_distributionমান এটির পূর্ণসংখ্যার [1, 100] এ এটি ম্যাপ করে তা মূলত এটি: একটি সংখ্যা তৈরি করে n। যদি সংখ্যাটি 2147483600 এর বেশি না হয়, তবে ফিরে যান (n - 1) / 21474836 + 1; অন্যথায়, একটি নতুন নম্বর দিয়ে আবার চেষ্টা করুন।

    এটি দেখতে সহজ হওয়া উচিত যে বিস্তৃত ক্ষেত্রে, দুটি nপ্রক্রিয়া কেবলমাত্র 16807 দ্বারা পৃথক হয় এই পদ্ধতির অধীনে [1, 100] এ একই সংখ্যা পাওয়া যাবে। প্রকৃতপক্ষে, কেউ আশা করতে পারে যে উত্পন্ন সংখ্যা প্রতি 21474836/16807 = 1278 সেকেন্ড বা 21.3 মিনিটের মধ্যে প্রায় এক দ্বারা বাড়বে, যা আপনার পর্যবেক্ষণগুলির সাথে বেশ ভাল সম্মত হয়।

MSVC এর default_random_engineহয় mt19937যা এই সমস্যা নেই।


36
আমি অবাক হয়েছি যে, এমন ভয়াবহ ডিফল্ট চয়ন করতে জিসিসির স্ট্যান্ডার্ড লাইব্রেরির বিকাশকারীদের কী ছিল?
কোডসইনচাউস

13
@ কোডস ইনচাউস আমি জানি না এটি সম্পর্কিত নয় তবে ম্যাকোস / আইওএস সরঞ্জামচইনে একই ভয়ঙ্কর এলোমেলো ইঞ্জিন ব্যবহার করা হয়েছে, যা rand()% 7 কে সর্বদা 0
ফুক্লিভি

7
@ LưuVĩnhPhúc ফিক্সিং rand()করা কিছুটা বোধগম্য (এটি হতাশ উত্তরাধিকারের বাজে কথা)। নতুন কোনও কিছুর জন্য ছিটে-স্তরের PRNG ব্যবহার করা অমার্জনীয়। এমনকি আমি এটি একটি স্ট্যান্ডার্ড লঙ্ঘনও বিবেচনা করব, যেহেতু স্ট্যান্ডার্ডটির জন্য "তুলনামূলকভাবে নৈমিত্তিক, অযোগ্যতা এবং / অথবা হালকা ওজনের ব্যবহারের জন্য কমপক্ষে গ্রহণযোগ্য ইঞ্জিনের আচরণ সরবরাহ করা দরকার" requires আপনার বাস্তব rand % 7উদাহরণের মতো তুচ্ছ ব্যবহারের ক্ষেত্রে এমনকি এটি কার্যকরভাবে বিপর্যয়কর হতে পারে না ।
CodeInChaos

4
@ কোডসআইএনচাউস কেন rand()কিছুটা বোধগম্য স্থির করছেন না ? এটি কি কেবল কারণেই এটি করার কথা ভাবেনি?
ব্যবহারকারী 253751

4
@ মিম্বিস এআইপিটি এতটাই ভাঙ্গা হয়েছে যে আপনি একটি স্বাধীন প্রতিস্থাপনের মাধ্যমে আরও ভাল হন যা সমস্ত সমস্যার সমাধান করে। 1) অ্যালগরিদম প্রতিস্থাপন একটি ব্রেকিং পরিবর্তন হতে পারে, তাই আপনার সম্ভবত পুরানো প্রোগ্রামগুলির জন্য একটি সামঞ্জস্যতা সুইচ প্রয়োজন। ২) এর বীজ srandখুব সহজেই অনন্য বীজ উত্পন্ন করতে পারে। 3) এটি একটি বাস্তবায়িত সংজ্ঞায়িত উপরের বাউন্ডের সাথে একটি পূর্ণসংখ্যা ফেরত দেয় যা কলকারীকে কোনওভাবে কাঙ্ক্ষিত পরিসরে একটি সংখ্যায় হ্রাস করতে হবে, যা সঠিকভাবে করা হলে rand()4 এর জন্য স্যান এপিআই সহ একটি প্রতিস্থাপন লেখার চেয়ে বেশি কাজ হয় ) এটি বিশ্বব্যাপী পরিবর্তনীয় অবস্থা ব্যবহার করে
কোডসইনচাউস

30

std::default_random_engineবাস্তবায়ন সংজ্ঞায়িত করা হয়। ব্যবহার করুন std::mt19937অথবা std::mt19937_64পরিবর্তে।

তদাতিরিক্ত std::timeএবং ctimeকার্যগুলি খুব সঠিক নয়, <chrono>পরিবর্তে শিরোনামে সংজ্ঞায়িত প্রকারগুলি ব্যবহার করুন :

#include <iostream>
#include <random>
#include <chrono>

int main()
{
    const int upper_bound = 100;
    const int lower_bound = 1;

    auto t = std::chrono::high_resolution_clock::now().time_since_epoch().count();

    std::mt19937 e;
    e.seed(static_cast<unsigned int>(t)); //Seed engine with timed value.
    std::uniform_int_distribution<int> u(lower_bound, upper_bound);

    std::cout << '#' << '\t' << "system time" << std::endl
    << "-------------------" << std::endl;

    for (int counter = 1; counter <= 5; counter++)
    {
        int secret = u(e);

        std::cout << secret << '\t' << t << std::endl;
    }   

    system("pause");
    return 0;
}

4
সিউডো-এলোমেলো পরিবর্তনশীল জেনারেটর বপন করার সময় কি আরও সঠিক সময় ব্যবহার করা বাঞ্ছনীয়? সম্ভবত এটি নিষ্পাপ, তবে এটি এনট্রপিটির সাথে পরিচয় করিয়ে দিলে মনে হয় যে ভুলত্রুটি প্রায় কাঙ্ক্ষিত হতে পারে। (যদি না আপনি বোঝাচ্ছেন এটি কম সুনির্দিষ্ট নয় এবং ফলস্বরূপ বস্তুগতভাবে কম সম্ভাব্য বীজ পাওয়া যায়))
নাট

15
আমি কেবল std::random_deviceআপনার র্যান্ডম জেনারেটর বীজ করার জন্য কারেন্ট_টাইমের পরিবর্তে ব্যবহার করার পরামর্শ দেব । অনুগ্রহ করে র্যান্ডম সম্পর্কে cppreferences উদাহরণ দেখুন।
আলেকসান্দার ফুলার

4
আপনি যদি চান না যে কেউ আপনার বীজ অনুমান করতে পারে (এবং সেইজন্য আপনার ক্রমটি পুনরুত্পাদন করে) তবে কম নির্ভুলতা বেশি এলোমেলো হওয়ার মতো নয়। আসুন আমরা চূড়ান্ত দিকে যাই: আপনার বীজকে পরের দিন (বা বছর?) গোল করুন -> অনুমান করা সহজ। ফেমটোসেকেন্ড নির্ভুলতা ব্যবহার করুন -> অনেক কিছু অনুমান করার জন্য ...
লিনাক

4
@ কেমিক্যাল ইঞ্জিনিয়ার এর গ্রানুলারিটি ctime1 সেকেন্ড। std::chronoবাস্তবায়নের গ্রানুলারিটি ব্যবহারকারী-সংজ্ঞায়িত, ডিফল্ট হিসাবে std::high_resolution_clock(ভিজ্যুয়াল স্টুডিওতে এটি টাইপডেফ std::steady_clock), ন্যানোসেকেন্ড তবে এর চেয়ে অনেক বেশি পরিমাপ বেছে নিতে পারে।
কেসি

4
@ লিনাক যদি আপনি ক্রিপ্টোগ্রাফিক বৈশিষ্ট্য চান তবে আপনি উপযুক্ত prng ব্যবহার করতে পারেন (এই উত্তরে ব্যবহৃত হয় নি)। এবং অবশ্যই সময়-ভিত্তিক বীজও প্রশ্নের বাইরে, প্রতিশ্রুত নির্ভুলতার বিষয়টি বিবেচনা করে না।
চথুলহু

-2

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

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

ওহ হ্যাঁ, লিনাক্সে দুটি এলোমেলো সংখ্যা জেনারেটর রয়েছে। একটি, ডিফল্টটি মডুলো 32 বিট এবং অন্যটি মডুলো mod৪ বিট bits আপনার পছন্দটি আপনার পরীক্ষার জন্য বা প্রকৃত ব্যবহারের জন্য নির্ভুলতার প্রয়োজনীয়তা এবং পরিমানের পরিমাণের উপর নির্ভর করে।


4
আমি নিশ্চিত না আপনি বীজ উত্পন্ন অ্যালগরিদম সম্পর্কে কেন কথা বলছেন। ওপি স্পষ্টভাবে একটি বীজ হিসাবে সিস্টেম সময় ব্যবহার করে। এছাড়াও, আপনি কিছু উল্লেখ যুক্ত করতে পারেনcollection of mouse, keyboard, network and time of day numbers
ডিফল্ট লোকাল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.