সম্পূর্ণ পরিসীমা জুড়ে এলোমেলো সংখ্যা তৈরি করুন


94

আমাকে একটি নির্দিষ্ট ব্যবধানে [সর্বোচ্চ; মিনিট] এর মধ্যে এলোমেলো সংখ্যা তৈরি করতে হবে।

এছাড়াও, এলোমেলো সংখ্যাগুলি একটি নির্দিষ্ট বিন্দুতে অবস্থিত নয়, বিরতিতে সমানভাবে বিতরণ করা উচিত।

আমি কৌতূহলী হিসাবে উত্পন্ন করছি:

for(int i=0; i<6; i++)
{
    DWORD random = rand()%(max-min+1) + min;
}

আমার পরীক্ষাগুলি থেকে, এলোমেলো সংখ্যাগুলি কেবলমাত্র একটি পয়েন্টের চারপাশে উত্পন্ন হয়।

Example
min = 3604607;
max = 7654607;

এলোমেলো সংখ্যা উত্পন্ন:

3631594
3609293
3630000
3628441
3636376
3621404

নীচের উত্তরগুলি থেকে: ঠিক আছে, RAND_MAX 32767 I আমি সি ++ উইন্ডোজ প্ল্যাটফর্মে আছি। অভিন্ন বিতরণ সহ এলোমেলো সংখ্যা তৈরি করার জন্য অন্য কোনও পদ্ধতি আছে কি?


4
একটি ডাইস-ও-ম্যাটিক তৈরি করুন: গেমসবাইমেল.com
জেরেট মিলার্ড

4
আমার ধারণা ছিল না যে সি ++ এর rand()অভিন্ন ছিল। আপনি কোন লাইব্রেরি ব্যবহার করছেন? cstdlib.hএর rand()অভিন্ন নয়: cplusplus.com/references/cstdlib/rand
মাইক ওয়ারেন

4
না, র‌্যান্ড () অভিন্ন (কিছু প্রথম বগি বাস্তবায়ন ব্যতীত)। যা অভিন্ন নয় তা পরিসীমা সীমাবদ্ধ করতে মডুলাস '%' অপারেটরটি ব্যবহার করছে। দেখুন stackoverflow.com/questions/2999075/... একটি সঠিক সমাধান জন্য, অথবা যদি আপনি 'arc4random_uniform' আছে প্রাপ্তিসাধ্য তারপর আপনি ব্যবহার সরাসরি পাশাপাশি পারবেন না।
জন মিচাম

@ এলিয়েন ০১: আপনি কি "জুতো" ("কেন র‌্যান্ড একটি খারাপ ধারণা" ইত্যাদি ইত্যাদি) দ্বারা একটিটির গৃহীত উত্তর পরিবর্তন করার বিষয়ে বিবেচনা করবেন? আমার উত্তরটি সত্যিই পুরানো।
পিটারচেন

নিস সাদা কাগজ সম্পর্কে C ++ 11 র্যান্ডম।
Pupsik

উত্তর:


158

randখারাপ ধারণা কেন

আপনি এখানে পেয়েছেন বেশিরভাগ উত্তরগুলি randফাংশন এবং মডুলাস অপারেটরটি ব্যবহার করে। এই পদ্ধতিটি অভিন্নভাবে সংখ্যা তৈরি করতে পারে না (এটি পরিসীমা এবং এর মানের উপর নির্ভর করে RAND_MAX), এবং তাই নিরুৎসাহিত করা হয়।

সি ++ 11 এবং একটি পরিসীমা জুড়ে প্রজন্ম

সি ++ এর সাথে একাধিক অন্যান্য বিকল্প উঠে এসেছে। যার এক চমত্কার চমত্কারভাবে, একটি সীমার মধ্যে একটি র্যান্ডম সংখ্যা জেনারেট করার জন্য, আপনার প্রয়োজনীয়তা দেখাচ্ছে: std::uniform_int_distribution। এখানে একটি উদাহরণ:

const int range_from  = 0;
const int range_to    = 10;
std::random_device                  rand_dev;
std::mt19937                        generator(rand_dev());
std::uniform_int_distribution<int>  distr(range_from, range_to);

std::cout << distr(generator) << '\n';

এবং এখানে চলমান উদাহরণ।

টেমপ্লেট ফাংশন কিছু সাহায্য করতে পারে:

template<typename T>
T random(T range_from, T range_to) {
    std::random_device                  rand_dev;
    std::mt19937                        generator(rand_dev());
    std::uniform_int_distribution<T>    distr(range_from, range_to);
    return distr(generator);
}

অন্যান্য এলোমেলো জেনারেটর

দ্য <random>হেডার বের্নুলি পইসন ও স্বাভাবিক সহ ডিস্ট্রিবিউশন বিভিন্ন ধরনের অসংখ্য অন্যান্য র্যান্ডম সংখ্যা জেনারেটর উপলব্ধ করা হয়।

আমি কীভাবে একটি ধারক বদল করতে পারি?

মানটি সরবরাহ করে std::shuffle, যা নিম্নলিখিত হিসাবে ব্যবহার করা যেতে পারে:

std::vector<int> vec = {4, 8, 15, 16, 23, 42};

std::random_device random_dev;
std::mt19937       generator(random_dev());

std::shuffle(vec.begin(), vec.end(), generator);

অ্যালগোরিদম একটি রৈখিক জটিলতার সাথে এলোমেলোভাবে উপাদানগুলিকে পুনরায় সাজিয়ে তুলবে।

বুস্ট.র্যান্ডম

আর একটি বিকল্প, যদি আপনার কাছে সি ++ 11 + সংকলক অ্যাক্সেস না থাকে তবে তা বুস্ট.র্যান্ডম ব্যবহার করা । এর ইন্টারফেসটি সি ++ 11 এর মতোই।


24
এই উত্তরটিতে মনোযোগ দিন, যেহেতু এটি অনেক বেশি আধুনিক।
gsamaras

এটি সঠিক উত্তর। ধন্যবাদ! তবুও, আমি এই কোডটির প্রতিটি পদক্ষেপের আরও গভীরভাবে বর্ণনা দেখতে চাই। যেমন এক mt19937প্রকার কি ?
অ্যাপোলো

@ এপোলো ডকুমেন্টেশনটিতে বলা হয়েছে "ম্যাটসুমোটো এবং নিশিমুরা, 1998-র 32-বিট মের্সেন টুইস্টার"। আমি ধরে নিচ্ছি যে এটি সিউডো-এলোমেলো সংখ্যা উত্পন্ন করার জন্য একটি অ্যালগরিদম।
জুতো

@ শো, প্রদত্ত পরিসরের জন্য, এটি একই ক্রমে সংখ্যাগুলি উত্পন্ন করে 1 9 6 2 8 7 1 4 7 7,। আপনি যখনই প্রোগ্রামটি চালাবেন তখন কীভাবে এটি এলোমেলোভাবে করবেন?

4
@ রিচার্ড বিকল্প কি?
জুতো

60

সতর্কতা: সম্পাদনা : rand()পরিসংখ্যান, সিমুলেশন, ক্রিপ্টোগ্রাফি বা গুরুতর কোনও কিছুর জন্য ব্যবহার করবেন না ।

সংখ্যাগুলি দেখতে এটি যথেষ্ট ভাল তাড়ার মধ্যে একটি টিপিক্যাল মানুষের জন্য র্যান্ডম, কোন।

আরও ভাল বিকল্পগুলির জন্য @ জেফফ্রে এর উত্তর দেখুন বা ক্রিপ্টো-সুরক্ষিত এলোমেলো সংখ্যার জন্য এই উত্তরটি দেখুন


সাধারণত, উচ্চ বিটগুলি কম বিটের চেয়ে আরও ভাল বিতরণ দেখায়, তাই সাধারণ উদ্দেশ্যে একটি রেঞ্জের এলোমেলো সংখ্যা উত্পন্ন করার প্রস্তাবিত উপায় হ'ল:

((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

দ্রষ্টব্য : নিশ্চিত করুন যে RAND_MAX + 1 প্রবাহিত হয় না (ধন্যবাদ ডেমি)!

বিভাগ ব্যবধানে একটি এলোমেলো সংখ্যা তৈরি করে [0, 1); এটি প্রয়োজনীয় ব্যাপ্তিতে "প্রসারিত করুন"। কেবলমাত্র যখন সর্বাধিক-মিনিট +1 RAND_MAX এর কাছাকাছি আসে আপনার কাছে মার্ক রান্সম পোস্ট করার মতো একটি "বিগআর্যান্ড ()" ফাংশন প্রয়োজন।

এটি মডিউলগুলির কারণে কিছু কাটা সমস্যা এড়ানো যায় যা আপনার সংখ্যা আরও খারাপ করতে পারে।


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


4
পছন্দসই পরিসর RAND_MAX ছাড়িয়ে না গেলেও বিগআর্যান্ড আরও ভাল ফলাফল দিতে পারে। বিবেচনা করুন যখন RAND_MAX কখন 32767 হয় এবং আপনি 32767 সম্ভাব্য মান চান - এই 32768 এ দু'টি র্যান্ডম সংখ্যার (শূন্য সহ) একই আউটপুটে মানচিত্রের দিকে যাচ্ছেন এবং অন্যদের মতো দ্বিগুণ হওয়ার সম্ভাবনা থাকে। একটি আদর্শ এলোমেলো সম্পত্তি খুব কমই!
মার্ক রান্সম

8
(RAND_MAX + 1) একটি খারাপ ধারণা। এটি রোলওভার এবং আপনাকে একটি নেতিবাচক মান দিতে পারে। এর মতো কিছু করা ভাল: ((ডাবল) RAND_MAX) + 1.0
ডেমি

4
@ পিটারচেন: আমার মনে হয় আপনি ডেমি যা বলছেন তা ভুল বুঝেছেন। তিনি এটিকে বোঝাতে চেয়েছিলেন: ( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min কেবল রূপান্তরটি দ্বিগুণ করতে এবং সমস্যা এড়াতে সরান।
মাকিং হাঁস

4
এছাড়াও, এটি কেবলমাত্র রেঞ্জের নীচে 32767 মান থেকে বিতরণকে সমানভাবে বিস্তৃত 32767 মানগুলিতে ব্যাপ্তি পরিবর্তন করে এবং অবশিষ্ট 4017233 মান কখনও এই অ্যালগরিদম দ্বারা নির্বাচিত হবে না।
মাকিং হাঁস

4
প্রদত্ত উত্তরটি ১. বন্ধ করে দেওয়া হয়েছে সঠিক সমীকরণটি: ((ডাবল) র‌্যান্ড () / (আরএএএ এমএএমএএমএক্স + ১.০)) * (সর্বাধিক-মিনিট) + মিনিট% না ব্যবহার করে * "সর্বোচ্চ-মিনিট +১" ব্যবহার করা হয় । আপনি যখন দেখবেন কেন আপনি ন্যূনতম = 0, সর্বোচ্চ = 1 করেন। পিটারচেন বা @ পিটার-মর্টেনসেন এটি সংশোধন করতে পারে।
davepc

17

আমি আর্টের রাজ্যটির সংক্ষিপ্ত সংক্ষিপ্ত বিবরণ দিয়ে 2015 এ অ্যাংরি জুতার এবং পিটারচেনের দুর্দান্ত উত্তরের পরিপূরক চাই:

কিছু ভাল পছন্দ

randutils

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

সর্বনিম্ন নমুনা: একটি ডাই রোল

#include <iostream>
#include "randutils.hpp"
int main() {
    randutils::mt19937_rng rng;
    std::cout << rng.uniform(1,6) << "\n";
}

এমনকি লাইব্রেরিতে যদি কেউ আগ্রহী না হয় তবে ওয়েবসাইট ( http://www.pcg-random.org/ ) সাধারণভাবে র্যান্ডম সংখ্যা জেনারেশন এবং বিশেষত সি ++ গ্রন্থাগার সম্পর্কে অনেক আকর্ষণীয় নিবন্ধ সরবরাহ করে।

বুস্ট.র্যান্ডম

Boost.Random (ডকুমেন্টেশন) হ'ল লাইব্রেরি যা অনুপ্রেরণা C++11জাগায় <random>, যার সাথে ইন্টারফেসের বেশিরভাগ অংশ ভাগ করে। যদিও তাত্ত্বিকভাবে বাহ্যিক নির্ভরতা হয়েও Boostএখন অবধি "অর্ধ-মানক" গ্রন্থাগারটির একটি স্ট্যাটাস রয়েছে এবং এর Randomমডিউলটি ভাল মানের র্যান্ডম সংখ্যা জেনারেশনের জন্য শাস্ত্রীয় পছন্দ হিসাবে বিবেচিত হতে পারে। সমাধানের ক্ষেত্রে এটি দুটি সুবিধার বৈশিষ্ট্যযুক্ত C++11:

  • এটি আরও পোর্টেবল, কেবল সি ++ 03 এর জন্য সংকলক সমর্থন প্রয়োজন
  • এটি random_deviceভাল মানের বীজ সরবরাহ করার জন্য সিস্টেম-নির্দিষ্ট পদ্ধতি ব্যবহার করে

একমাত্র ছোট ত্রুটিটি হল মডিউল অফারটি random_deviceকেবল শিরোনাম নয়, একটিকে সংকলন করতে এবং লিঙ্ক করতে হয় boost_random

সর্বনিম্ন নমুনা: একটি ডাই রোল

#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>

int main() {
    boost::random::random_device                  rand_dev;
    boost::random::mt19937                        generator(rand_dev());
    boost::random::uniform_int_distribution<>     distr(1, 6);

    std::cout << distr(generator) << '\n';
}

যদিও সর্বনিম্ন নমুনাটি এটির কাজটি ভাল করে, বাস্তব প্রোগ্রামগুলিতে একজোড়া উন্নতি ব্যবহার করা উচিত:

  • করতে mt19937একটিthread_local : জেনারেটর বেশ দ্বিধাহীনভাবে আছে (> 2 কিলোবাইট) এবং ভাল স্ট্যাক বরাদ্দ করা হয় না
  • mt19937একাধিক পূর্ণসংখ্যা সহ বীজ : মার্সেন টুইস্টার একটি বড় রাষ্ট্র রয়েছে এবং প্রারম্ভিককরণের সময় আরও এনট্রপির সুবিধা নিতে পারে

কিছু খুব ভাল-না পছন্দ

সি ++ 11 গ্রন্থাগার

সর্বাধিক অভিহিতযোগ্য সমাধান হওয়ার <random>পরেও গ্রন্থাগারটি এমনকি প্রাথমিক প্রয়োজনগুলির জন্যও তার ইন্টারফেসের জটিলতার পরিবর্তে খুব বেশি প্রস্তাব দেয় না। ত্রুটি আছেstd::random_device : স্ট্যান্ডার্ডটি তার আউটপুটটির জন্য কোনও ন্যূনতম মানের আদেশ দেয় না (যতক্ষণ না entropy()প্রত্যাবর্তন হয় 0) এবং ২০১৫ সাল পর্যন্ত, মিনিজিডাব্লু (সর্বাধিক ব্যবহৃত সংকলক নয়, তবে একটি বিশেষ পছন্দ) সর্বদা 4সর্বনিম্ন নমুনায় মুদ্রিত হবে ।

সর্বনিম্ন নমুনা: একটি ডাই রোল

#include <iostream>
#include <random>
int main() {
    std::random_device                  rand_dev;
    std::mt19937                        generator(rand_dev());
    std::uniform_int_distribution<int>  distr(1, 6);

    std::cout << distr(generator) << '\n';
}

যদি প্রয়োগটি পচা না হয় তবে এই সমাধানটি বুস্টের সমতুল্য হওয়া উচিত এবং একই পরামর্শগুলি প্রয়োগ করা হবে।

গডোটের সমাধান

সর্বনিম্ন নমুনা: একটি ডাই রোল

#include <iostream>
#include <random>

int main() {
    std::cout << std::randint(1,6);
}

এটি একটি সহজ, কার্যকর এবং ঝরঝরে সমাধান। কেবল ত্রুটিপূর্ণ, এটি সংকলন করতে কিছুক্ষণ সময় লাগবে - প্রায় দুই বছর, প্রদান করা সি ++ 17 সময়মতো প্রকাশিত হয় এবং পরীক্ষামূলকভাবেrandint ফাংশনটি নতুন স্ট্যান্ডার্ডে অনুমোদিত হয়। সম্ভবত সেই সময়ের মধ্যে বীজ মানের উপর গ্যারান্টি উন্নত হবে।

সবচেয়ে খারাপ-ভাল সমাধান

সর্বনিম্ন নমুনা: একটি ডাই রোল

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

int main() {
    std::srand(std::time(nullptr));
    std::cout << (std::rand() % 6 + 1);
}

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

অ্যাকাউন্টিং ট্রল সমাধান

সর্বনিম্ন নমুনা: একটি ডাই রোল

#include <iostream>

int main() {
    std::cout << 9;   // http://dilbert.com/strip/2001-10-25
}

যদিও 9 নিয়মিত ডাই রোলের জন্য কিছুটা অস্বাভাবিক পরিণতি হয় তবে এই সমাধানে ভাল গুণাবলীর চমৎকার সংমিশ্রণকে একজনকে প্রশংসা করতে হয়, যা দ্রুত, সহজতম, সবচেয়ে ক্যাশে-বান্ধব এবং সবচেয়ে বহনযোগ্য এক হিসাবে পরিচালিত হয়। 9 এর সাথে 4 প্রতিস্থাপনের মাধ্যমে যেকোন ধরণের ডানজন এবং ড্রাগন মারা যাওয়ার জন্য নিখুঁত জেনারেটর পাওয়া যায়, তবুও চিহ্ন, বোঝা মান 1, 2 এবং 3 এড়িয়ে চলা কেবলমাত্র ছোট্ট ত্রুটিটি হ'ল, দিলবার্টের অ্যাকাউন্টিং ট্রলগুলির খারাপ মেজাজের কারণে, এই প্রোগ্রামটি প্রকৃতপক্ষে অপরিবর্তিত আচরণকে উত্সাহ দেয়।


randutilsগ্রন্থাগার এখন PCG বলা হয়।
tay10r

10

যদি RAND_MAX32767 হয়, আপনি সহজেই বিটের সংখ্যা দ্বিগুণ করতে পারেন।

int BigRand()
{
    assert(INT_MAX/(RAND_MAX+1) > RAND_MAX);
    return rand() * (RAND_MAX+1) + rand();
}

আমি মনে করি না এটি কাজ করে। সিউডো এলোমেলো সংখ্যা জেনারেটর সাধারণত নিরোধক হয়। উদাহরণস্বরূপ, যদি প্রথম randকলটি রিটার্ন দেয় 0x1234এবং দ্বিতীয়টি হয় 0x5678, তবে আপনি পাবেন 0x12345678। এটিই কেবলমাত্র এমন নম্বর যা আপনি এটির সাথে শুরু করতে পারেন 0x1234, কারণ পরবর্তী নম্বরটি সর্বদা থাকবে 0x5678। আপনি 32-বিট ফলাফল পান তবে আপনার কাছে কেবল 32768 সম্ভাব্য সংখ্যা রয়েছে।
ব্যবহারকারী 694733

@ ব্যবহারকারী 694733 একটি ভাল এলোমেলো সংখ্যার জেনারেটরের একটি পিরিয়ড রয়েছে যা উত্পন্ন আউটপুটগুলির সংখ্যার চেয়ে বেশি হয়, সুতরাং 0x1234 সর্বদা 0x5678 অনুসরণ করা হবে না ।
মার্ক

9

আপনি যদি সক্ষম হন তবে বুস্টটি ব্যবহার করুন । তাদের এলোমেলো লাইব্রেরিটি দিয়ে আমার শুভকামনা রয়েছে ।

uniform_int আপনি যা চান তা করা উচিত


আমি ইউনিফর্ম_িন্ট নিয়ে মেরসিনে টুইস্টার নিয়ে কিছু কাজ করেছি এবং দুর্ভাগ্যক্রমে নির্দিষ্ট রেঞ্জের জন্য ইউনিফর্ম_িন্ট দ্বারা প্রত্যাবর্তিত মানগুলি যতটা প্রত্যাশা করেছিলাম তেমন অভিন্ন নয়। উদাহরণস্বরূপ ইউনিফর্ম_িন্ট <> (0, 3) 1 বা 2 এর চেয়ে বেশি 0 উত্পাদন করতে পারে
ScaryAardvark

@ সেকারিআর্ডভার্ক যা তখনকার একটি খারাপ বাস্তবায়ন বলে মনে হচ্ছে uniform_int। পক্ষপাতহীন আউটপুট উত্পন্ন করা বেশ সহজ, এখানে একাধিক প্রশ্ন রয়েছে যা পদ্ধতিটি দেখায়।
মার্ক র্যানসোম

নিবন্ধন করুন হ্যাঁ, আমি পুরোপুরি একমত হয়েছি।
ScaryAardvark

8

আপনি যদি এলোমেলো সম্পর্কে উদ্বিগ্ন হন এবং গতির বিষয়ে না হন তবে আপনার একটি নিরাপদ র্যান্ডম নম্বর জেনারেশন পদ্ধতি ব্যবহার করা উচিত। এটি করার বিভিন্ন উপায় রয়েছে ... ওপেনএসএসএল এর র্যান্ডম নম্বর জেনারেটর ব্যবহার করা সবচেয়ে সহজ ।

আপনি কোনও এনক্রিপশন অ্যালগরিদম ( AES এর মতো ) ব্যবহার করে নিজের লেখাও লিখতে পারেন । একটি বীজ এবং IV বাছাই করে এবং তারপরে ক্রমাগত এনক্রিপশন ফাংশনের আউটপুটটিকে পুনরায় এনক্রিপ্ট করে। ওপেনএসএসএল ব্যবহার করা সহজ, তবে ম্যানলি কম।


আমি কোনও তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করতে পারি না? আমি কেবল সি ++ তে সীমাবদ্ধ।
আনন্দ

তারপরে ম্যানলি রুটে যান, এইএস বা অন্য কোনও এনক্রিপশন অ্যালগরিদম প্রয়োগ করুন।
সোপবক্স

4
আরসি 4 কোডের পক্ষে তুচ্ছ, এবং সমস্ত ব্যবহারিক উদ্দেশ্যে (ডাব্লুইইপি ছাড়া, তবে এটি পুরোপুরি আরসি 4 এর দোষ নয়) যথেষ্ট পরিমাণে এলোমেলো। আমি এটি বোঝাতে চাইছি এটি অবিশ্বাস্যভাবে তুচ্ছ কোড মত, 20 লাইন বা তাই। উইকিপিডিয়ায় প্রবেশের সিউডো-কোড রয়েছে।
স্টিভ জেসোপ

4
আপনি তৃতীয় পক্ষের কোডটি কেন ব্যবহার করতে পারবেন না? যদি এটি কোনও হোমওয়ার্কের প্রশ্ন হয় তবে আপনার এ কথাটি বলা উচিত, কারণ এই ক্ষেত্রে সম্পূর্ণ সমাধান দেওয়ার পরিবর্তে অনেক লোক সহায়ক ইঙ্গিত দেয়। যদি এটি কোনও হোমওয়ার্ক না হয় তবে "তৃতীয় পক্ষের কোড নয়" বলে লোকটিকে লাথি মারুন, কারণ তিনি একজন মরন।
দেবসোলার

দ্বারা OpenSSL RAND () ফাংশন ডক্সে আরো সরাসরি লিঙ্ক: openssl.org/docs/crypto/rand.html#
DevSolar

5

RAND_MAXআপনার নির্দিষ্ট সংকলক / পরিবেশের দিকে নজর দেওয়া উচিত । আমি মনে করি আপনি যদি rand()এলোমেলো 16-বিট সংখ্যা তৈরি করে থাকেন তবে আপনি এই ফলাফলগুলি দেখতে পাবেন । (আপনি মনে করছেন এটি 32-বিট নম্বর হবে)।

আমি এই উত্তরটি প্রতিশ্রুতি দিতে পারি না তবে দয়া করে আপনার মানটি RAND_MAXএবং আপনার পরিবেশ সম্পর্কে আরও কিছু বিশদ পোস্ট করুন।


3

RAND_MAXআপনার সিস্টেমে কী আছে তা পরীক্ষা করুন - আমি অনুমান করছি এটি কেবল 16 বিট, এবং আপনার পরিসর এটির জন্য খুব বড়।

এর বাইরে এই আলোচনাটি দেখুন: একটি পছন্দসই ব্যাপ্তির মধ্যে র‌্যান্ডম পূর্ণসংখ্যার উত্পাদন এবং সি র‌্যান্ড () ফাংশনটি ব্যবহার করার জন্য নোটগুলি ।


ঠিক আছে RAND_MAX 32767. আমি সি ++ উইন্ডোজ প্ল্যাটফর্মে আছি .. অভিন্ন বিতরণ সহ এলোমেলো সংখ্যা তৈরি করার জন্য অন্য কোনও পদ্ধতি আছে কি?
আনন্দ

2

এটি কোড নয়, তবে এই যুক্তি আপনাকে সাহায্য করতে পারে।

static double rnd(void)
{
   return (1.0 / (RAND_MAX + 1.0) * ((double)(rand())) );
}

static void InitBetterRnd(unsigned int seed)
{
    register int i;
    srand( seed );
    for( i = 0; i < POOLSIZE; i++){
        pool[i] = rnd();
    }
}

 // This function returns a number between 0 and 1
 static double rnd0_1(void)
 {
    static int i = POOLSIZE-1;
    double r;

    i = (int)(POOLSIZE*pool[i]);
    r = pool[i];
    pool[i] = rnd();
    return (r);
}

2

আপনি যদি সংখ্যাটি পরিসীমাতে সমানভাবে বিতরণ করতে চান তবে আপনার রেঞ্জটি অনেকগুলি সমান বিভাগে বিভক্ত হওয়া উচিত যা আপনার প্রয়োজনীয় পয়েন্টগুলির প্রতিনিধিত্ব করে। তারপরে প্রতিটি বিভাগের জন্য ন্যূনতম / সর্বোচ্চের সাথে একটি এলোমেলো নম্বর পান।

অন্য নোট হিসাবে, সম্ভবত আপনি ব্যবহার rand()করা উচিত নয় কারণ এটি এলোমেলো সংখ্যা উত্পন্ন করার পক্ষে এটি খুব ভাল নয়। আপনি কোন প্লাটফর্মটি চালাচ্ছেন তা আমি জানি না, তবে সম্ভবত আপনি আরও ভাল কোনও ফাংশন বলতে পারেন random()


1

[low, high)সামগ্রিক পরিসর যতক্ষণ RAND_MAX এর চেয়ে কম থাকে ততক্ষণ এটি ভাসা ব্যবহার না করেই পরিসীমাটির উপরে একরকম বিতরণ সরবরাহ করতে হবে ।

uint32_t rand_range_low(uint32_t low, uint32_t high)
{
    uint32_t val;
    // only for 0 < range <= RAND_MAX
    assert(low < high);
    assert(high - low <= RAND_MAX);

    uint32_t range = high-low;
    uint32_t scale = RAND_MAX/range;
    do {
        val = rand();
    } while (val >= scale * range); // since scale is truncated, pick a new val until it's lower than scale*range
    return val/scale + low;
}

আর RAND_MAX এর চেয়ে বড় মানের জন্য আপনি এমন কিছু চান

uint32_t rand_range(uint32_t low, uint32_t high)
{
    assert(high>low);
    uint32_t val;
    uint32_t range = high-low;
    if (range < RAND_MAX)
        return rand_range_low(low, high);
    uint32_t scale = range/RAND_MAX;
    do {
        val = rand() + rand_range(0, scale) * RAND_MAX; // scale the initial range in RAND_MAX steps, then add an offset to get a uniform interval
    } while (val >= range);
    return val + low;
}

মোটামুটি এইভাবে স্ট্যান্ড :: ইউনিফর্ম_িন্ট_ডিসিস্ট্রেশন জিনিসগুলি করে।


0

তাদের প্রকৃতির দ্বারা, এলোমেলো সংখ্যার একটি ছোট নমুনা সমানভাবে বিতরণ করতে হবে না। তারা এলোমেলো, সর্বোপরি। আমি সম্মত হই যে যদি কোনও এলোমেলো সংখ্যার জেনারেটর এমন নম্বর উত্পন্ন করে যা ধারাবাহিকভাবে গোষ্ঠীযুক্ত বলে মনে হয়, তবে সম্ভবত এটিতে কিছু ভুল আছে।

তবে মনে রাখবেন যে এলোমেলোভাবে প্রয়োজনীয়তা অভিন্ন নয়।

সম্পাদনা করুন: আমি পরিষ্কার করতে "ছোট নমুনা" যুক্ত করেছি।


"অভিন্ন বিতরণ" এর একটি সুস্পষ্ট সংজ্ঞাযুক্ত অর্থ রয়েছে এবং মানক র্যান্ডম জেনারেটর সাধারণত কাছে আসে।
পিটারচেন

হ্যাঁ, আপনি ঠিক বলেছেন, এলোমেলো সংখ্যা জেনারেটরের এমন আউটপুট তৈরি করা উচিত যা সময়ের সাথে সাথে তার বিতরণে সাধারণত অভিন্ন। আমার অনুমান আমার বক্তব্যটি হ'ল অল্প সংখ্যক উদাহরণের (উদাহরণে প্রদর্শিত 6) আউটপুট সর্বদা অভিন্ন হবে না।
ক্লুজ

ক্লুজে ঠিক আছে। একটি ছোট নমুনায় ইউনিফর্ম বিতরণ ইঙ্গিত দেয় যে নমুনাটি অবশ্যই এলোমেলো নয়
বিল করুন

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

4
উল্লেখযোগ্য বিতরণগুলি কোনওভাবেই নন-এলোমেলোতা নির্দেশ করে: আমি মনে করি বিলটির অর্থ হ'ল সমান-দুরত্বের ফলাফলগুলিও সন্দেহজনক। ওপিতে, 6 মানগুলি 32k / 4M বা কাঙ্ক্ষিত ব্যাপ্তির <1% ব্যাপ্তিতে থাকে। এটির পক্ষে মিথ্যা ইতিবাচক হওয়ার সম্ভাবনা খুব তর্ক করার পক্ষে খুব ছোট।
স্টিভ জেসপ

0

1 এবং 10 এর মধ্যে সংখ্যার জন্য 3 র্যান্ড দ্বারা প্রদত্ত সমাধানটি হ'ল:

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

আপনার ক্ষেত্রে, এটি হবে:

j = min + (int) ((max-min+1) * (rand() / (RAND_MAX + 1.0)));

অবশ্যই, এটি নিখুঁত এলোমেলোতা বা অভিন্নতা নয় কারণ কিছু অন্যান্য বার্তাগুলি নির্দেশ করছে তবে এটি বেশিরভাগ ক্ষেত্রেই যথেষ্ট।


4
এটি কেবল বিতরণটিকে আরও বেশি উপস্থিত হতে পুনরায়
সাজিয়েছে

0

@ সমাধান ((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

সতর্কতা : প্রসারিত এবং সম্ভাব্য নির্ভুলতা ত্রুটির কারণে ভুলে যাবেন না (এমনকি RAND_MAX যথেষ্ট পরিমাণে হলেও), আপনি কেবলমাত্র সমানভাবে বিতরণ করা "বিন" তৈরি করতে সক্ষম হবেন এবং [কমপক্ষে, সর্বাধিক] সমস্ত সংখ্যা নয় not


@ সমাধান: বিগ্র্যান্ড

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


তথ্য : আপনার পদ্ধতির (মডুলো) যতক্ষণ না র্যান্ড () এর ব্যাপ্তি আপনার অন্তর সীমা ছাড়িয়ে যায় এবং র্যান্ড () "অভিন্ন" থাকে ততক্ষণ "ঠিক"। সর্বাধিক প্রথম সর্বোচ্চ - মিনিটের সংখ্যাগুলির জন্য ত্রুটিটি 1 / (RAND_MAX +1)।

এছাড়াও, আমি সি ++ 11 এও নতুন এলোমেলো প্যাকেজটিতে স্যুইচ করার পরামর্শ দিচ্ছি , যা র‌্যান্ড () এর চেয়ে আরও ভাল এবং আরও বিভিন্ন ধরণের বাস্তবায়নের প্রস্তাব দেয়।


0

এই সমাধানটি আমি নিয়ে এসেছি:

#include "<stdlib.h>"

int32_t RandomRange(int32_t min, int32_t max) {
    return (rand() * (max - min + 1) / (RAND_MAX + 1)) + min;
}

এটি একটি বালতি সমাধান, ধারণাটি সমাধানের মতো rand() / RAND_MAXযা 0-1 এর মধ্যে ভাসমান পয়েন্টের সীমা পেতে এবং তারপরে এটি একটি বালতিতে গোল করে। তবে এটি বিশুদ্ধরূপে পূর্ণসংখ্যার গণিত ব্যবহার করে এবং মানটি নিকটতম বালতিতে গোল করার জন্য পূর্ণসংখ্যা বিভাগ মেঝে গ্রহণের সুবিধা গ্রহণ করে।

এটি কয়েকটি অনুমান করে। প্রথমত, এটি ধরে নেয় যে RAND_MAX * (max - min + 1)সবসময় একটি এর মধ্যে ফিট হয়ে যায় int32_t। যদি RAND_MAX32767 হয় এবং 32 বিট ইনট গণনাগুলি ব্যবহার করা হয় তবে আপনার সর্বাধিক পরিসীমা 32767 হতে পারে your যদি আপনার বাস্তবায়নের অনেক বড় RAND_MAX থাকে তবে আপনি int64_tগণনার জন্য বৃহত্তর পূর্ণসংখ্যার (পছন্দ ) ব্যবহার করে এটি কাটিয়ে উঠতে পারেন । দ্বিতীয়ত, যদি int64_tব্যবহৃত হয় তবে RAND_MAXএটি এখনও 32767 এর চেয়েও বড় রেঞ্জের হয়RAND_MAX হয় তবে সম্ভাব্য আউটপুট সংখ্যায় "গর্ত" পেতে শুরু করবে তার । স্কেলিং থেকে নেওয়া যে কোনও সমাধানের সাথে এটি সম্ভবত সবচেয়ে বড় সমস্যাrand()

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


-1

অবশ্যই, নিম্নলিখিত কোডটি আপনাকে এলোমেলো সংখ্যাগুলি দেবে না তবে সিউডো এলোমেলো নম্বর দেবে। নিম্নলিখিত কোড ব্যবহার করুন

#define QUICK_RAND(m,n) m + ( std::rand() % ( (n) - (m) + 1 ) )

উদাহরণ স্বরূপ:

int myRand = QUICK_RAND(10, 20);

আপনার অবশ্যই ফোন করা উচিত

srand(time(0));  // Initialize random number generator.

অন্যথায় সংখ্যা এলোমেলো কাছাকাছি হবে না।


4
প্রশ্নটি অভিন্ন বন্টনের জন্য জিজ্ঞাসা করছে। এই প্রস্তাবিত সমাধান অভিন্ন বিতরণ উত্পাদন করবে না। স্ট্যান্ডার্ড সি ++ লাইব্রেরিতে সিউডো-এলোমেলো সংখ্যা জেনারেশনের সুবিধা রয়েছে । সেই না , অভিন্ন বন্টন প্রদান করে অনুরোধ করা হয়েছে।
IInspectable

-3

আমি এটি ইন্টারনেটে সন্ধান করেছি। এই কাজ করা উচিত:

DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));

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

এটি আমার জন্য সবচেয়ে ভাল কাজ করে ... আমি এই সূত্র সঙ্গে ভাল বিতরণ র্যান্ডম সংখ্যা পেতে সক্ষম নই ..
আনন্দ

4
যদি আপনার পরিসর RAND_MAX ছাড়িয়ে যায়, ফলাফলগুলি অভিন্ন হতে পারে না । এটি হ'ল, পরিসীমাটিতে এমন মান রয়েছে যা আপনার ফাংশনকে কতবার কল করে তা উপস্থাপন করা হবে না।
ডিএমকেই --- প্রাক্তন-মডারেটর বিড়ালছানা

4
এছাড়াও, যদি সর্বোচ্চ এবং সর্বনিম্ন উভয় স্বাক্ষরযুক্ত স্বাক্ষরিত হয় এবং সর্বনিম্ন 0 হয়, এবং সর্বনিম্ন হয় MAX_UINT, তবে ((সর্বোচ্চ) - (সর্বনিম্ন) +1 0 হবে এবং ফলাফল সর্বদা 0 হবে। এই ধরণের গণিত করছেন ওভারফ্লো! যেমনটি ডেম্কে লিখেছেন, এটি গন্তব্য সীমার উপরে বিতরণকে প্রসারিত করে তবে RAND_MAX এর চেয়ে বেশি অনন্য মানের গ্যারান্টি দেয় না।
jesup
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.