Java.util.Random আসলেই কি এলোমেলো? আমি কিভাবে 52 জেনারেট করতে পারি! (ঘটনামূলক) সম্ভাব্য ক্রম?


202

আমি Random (java.util.Random)52 টি কার্ডের একটি ডেকে সাফল্যের জন্য ব্যবহার করছি। 52 আছে! (8.0658175e + 67) সম্ভাবনা। তবুও, আমি খুঁজে পেয়েছি যে এর জন্য বীজ java.util.Randomএকটি long, যা 2 ^ 64 (1.8446744e + 19) এ অনেক ছোট।

এখান থেকে, আমি সন্দেহজনক যে java.util.Random সত্যিই এলোমেলো কিনা ; এটি আসলে সমস্ত 52 উত্পাদন করতে সক্ষম! সম্ভাবনার?

যদি তা না হয় তবে কীভাবে আমি নির্ভরযোগ্যভাবে একটি আরও ভাল এলোমেলো ক্রম উত্পন্ন করতে পারি যা সমস্ত 52 উত্পাদন করতে পারে! সম্ভাবনার?


21
"আমি কীভাবে নিশ্চিতভাবে 52 এরও বেশি একটি বাস্তব এলোমেলো সংখ্যা তৈরি করতে পারি !" থেকে প্রাপ্ত নম্বরগুলি Randomকখনই আসল এলোমেলো সংখ্যা নয়। এটি পিআরএনজি, যেখানে পি "সিডো"। আসল এলোমেলো সংখ্যার জন্য আপনার এলোমেলো উত্সের প্রয়োজন (যেমন র্যান্ডম.org)।
টিজে ক্রাউডার

7
@ জিমগারিসন ওপি-র পরে এটি নয়। তিনি 10 ^ 68 সম্ভাব্য সিকোয়েন্স সম্পর্কে কথা বলছেন। যেহেতু প্রতিটি সিউডো-এলোমেলো ক্রমটি এর বীজ দ্বারা চিহ্নিত করা হয়, ওপি বলছেন যে সর্বাধিক 2 ^ 64 টি বিভিন্ন ক্রম হতে পারে।
ডেসব্লিংকনলাইট

6
আমি মনে করি এটি একটি আকর্ষণীয় প্রশ্ন, এবং এটি সম্পর্কে চিন্তা করা মূল্যবান। তবে আমি আপনার সমস্যার প্রসঙ্গটি নিয়ে ভাবতে সহায়তা করতে পারি না: এটি ঠিক কী এটি সমস্ত 52 জেনারেট করতে সক্ষম হওয়ার প্রয়োজনীয়তার দিকে নিয়ে যায়! একাধিক বিন্যাসন? উদাহরণস্বরূপ, বাস্তব-বিশ্বের সেতুতে আমরা ডেকটি সাফল্যমুক্ত করতে পারি এবং একসাথে একটি কার্ড ডিল করতে পারি, তবুও কেবলমাত্র e 6e11 বিভিন্ন হাত রয়েছে যেহেতু অনেকগুলি পৃথক ক্রিয়াকলাপ একই হাতের ফলস্বরূপ। অন্য দিকে ভাবছেন, আপনার কি বিশেষত ৫২! এর জন্য কোনও সমাধানের দরকার আছে, বা আপনার কী এমন এক সাধারণের প্রয়োজন যা বলা যাক, দুটি ডেকে একসাথে (104 / / (2 ** 52) সম্ভাবনা বা ~ 2e150) বদলানো?
এনপিই

9
@ এনপিই - সলিটায়ার (ক্লন্ডিকে) উদাহরণস্বরূপ নিন, 52! সম্ভাব্য হাতের সংখ্যা
হ'ল

3
আমি মনে করি এটি একটি আকর্ষণীয় পঠন: superuser.com/a/712583
ডেনিস_ই

উত্তর:


153

আপনার প্রশ্নটি যা বোঝায় তার চেয়ে এলোমেলোভাবে নির্ধারণের জন্য একই সাথে আরও এবং কম এলোমেলো প্রয়োজন। আমাকে ব্যাখ্যা করতে দাও.

খারাপ খবর: আরও এলোমেলো প্রয়োজন।

আপনার পদ্ধতির মৌলিক ত্রুটিটি হ'ল এটি এনট্রপির 64 বিট (এলোমেলো বীজ) ব্যবহার করে 226 ডলার সম্ভাবনার মধ্যে বেছে নেওয়ার চেষ্টা করছে । মোটামুটি 22 2 226 এর মধ্যে বেছে নেওয়ার জন্য আপনাকে 64 এর পরিবর্তে 226 বিট এনট্রপি উত্পন্ন করার উপায় খুঁজে বের করতে হবে।

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

সুসংবাদ: কম এলোমেলো প্রয়োজন।

আপনার 226 টি এলোমেলো বিটগুলি পরে, বাকীগুলি নির্বিচারে করা যায় এবং তাই এর বৈশিষ্ট্যগুলি java.util.Randomঅপ্রাসঙ্গিক করা যায় । এখানে কিভাবে।

ধরা যাক আমরা সমস্ত 52 উত্পাদন করি! অনুমতি (আমার সাথে বহন করুন) এবং সেগুলি ডিকোসোগ্রাফিকভাবে বাছাই করুন।

একাধিক বিন্যাসন চয়ন করার আমাদের যা দরকার এর মধ্যে একটি একক র্যান্ডম পূর্ণসংখ্যা 0এবং 52!-1। সেই পূর্ণসংখ্যাটি হ'ল আমাদের 226 বিট ইন্ট্রপি। আমাদের অনুমতি অনুসারে বাছাই করা তালিকায় এটি একটি সূচক হিসাবে ব্যবহার করব। যদি এলোমেলো সূচকটি সমানভাবে বিতরণ করা হয়, তবে কেবল আপনাকেই নিশ্চিত নয় যে সমস্ত অনুক্রম নির্বাচন করা যেতে পারে, সেগুলি সজ্জিতভাবে বেছে নেওয়া হবে (যা প্রশ্ন জিজ্ঞাসা করছে তার চেয়ে শক্তিশালী গ্যারান্টি)।

এখন, আপনাকে আসলে এই সমস্ত অনুমতি উত্পন্ন করার দরকার নেই। আমাদের অনুমানের অনুসারে বাছাই করা তালিকায় এলোমেলোভাবে নির্বাচিত অবস্থানের ভিত্তিতে আপনি সরাসরি একটি উত্পাদন করতে পারেন। এটি লেহমার [1] কোড ব্যবহার করে ও (এন 2 ) সময়ে করা যেতে পারে (এছাড়াও সংখ্যার ক্রম এবং ফ্যাকটোরিয়াডিক নম্বর সিস্টেমটি দেখুন )। এখানে এন আপনার ডেকের আকার, অর্থাৎ 52।

এই স্ট্যাকওভারফ্লো উত্তরে একটি সি বাস্তবায়ন রয়েছে । সেখানে বেশ কয়েকটি পূর্ণসংখ্যার ভেরিয়েবল রয়েছে যা এন = 52 এর জন্য উপচে পড়বে তবে ভাগ্যক্রমে জাভাতে আপনি এটি ব্যবহার করতে পারেন java.math.BigInteger। বাকী গণনাগুলি প্রায় হিসাবেই প্রতিলিপি করা যায়:

public static int[] shuffle(int n, BigInteger random_index) {
    int[] perm = new int[n];
    BigInteger[] fact = new BigInteger[n];
    fact[0] = BigInteger.ONE;
    for (int k = 1; k < n; ++k) {
        fact[k] = fact[k - 1].multiply(BigInteger.valueOf(k));
    }

    // compute factorial code
    for (int k = 0; k < n; ++k) {
        BigInteger[] divmod = random_index.divideAndRemainder(fact[n - 1 - k]);
        perm[k] = divmod[0].intValue();
        random_index = divmod[1];
    }

    // readjust values to obtain the permutation
    // start from the end and check if preceding values are lower
    for (int k = n - 1; k > 0; --k) {
        for (int j = k - 1; j >= 0; --j) {
            if (perm[j] <= perm[k]) {
                perm[k]++;
            }
        }
    }

    return perm;
}

public static void main (String[] args) {
    System.out.printf("%s\n", Arrays.toString(
        shuffle(52, new BigInteger(
            "7890123456789012345678901234567890123456789012345678901234567890"))));
}

[1] লেহেরারের সাথে বিভ্রান্ত হওয়ার দরকার নেই । :)


7
হেই, এবং আমি নিশ্চিত ছিলাম যে লিঙ্কটি শেষের দিকে নিউ ম্যাথ হবে । :-)
টিজে ক্রাউডার

5
@ টিজে ক্রাউডার: এটি প্রায় ছিল! এটি অসীম স্বতন্ত্রভাবে পার্থক্যযোগ্য রিমান্নিয়ান বহুগুণে এটি গড়িয়েছিল। :-)
এনপিই

2
লোকগুলি ক্লাসিকগুলির প্রশংসা করতে দেখে ভাল। :-)
টিজে ক্রাউডার

3
আপনি জাভাতে এলোমেলো 226 বিট পাবেন ? দুঃখিত, আপনার কোড এর উত্তর দেয় না।
থারস্টেন এস।

5
আপনি কী বলতে চাইছেন তা আমি বুঝতে পারছি না, জাভা র্যান্ডম () এনট্রপির 64 বিট সরবরাহ করবে না। ওপি একটি অনির্ধারিত উত্সকে বোঝায় যা পিআরএনজি বীজের জন্য 64 বিট উত্পাদন করতে পারে। এটি ধরে নেওয়ার অর্থ হয় যে আপনি একই উত্সটি 226 বিটের জন্য জিজ্ঞাসা করতে পারেন।
মনিকাকে ক্ষতিগ্রস্ত করা বন্ধ করুন

60

আপনার বিশ্লেষণ ঠিক কিনা: কোনো নির্দিষ্ট বীজ সঙ্গে একটি সিউডো-রেণ্ডম সংখ্যা উত্পাদক seeding একটি এলোমেলো পর একই ক্রম উত্পাদ হবে, একাধিক বিন্যাসন আপনি 2 প্রাপ্ত পারে সংখ্যা সীমিত 64 । এই দাবিটি পরীক্ষামূলকভাবেCollection.shuffle দু'বার কল করে, Randomএকই বীজের সাথে আরম্ভকৃত কোনও বস্তুটি পাস করে এবং দুটি এলোমেলো পরিবর্তনগুলি অভিন্ন বলে পর্যবেক্ষণ করে যাচাই করা সহজ

এর একটি সমাধান, তারপরে, এলোমেলো সংখ্যার জেনারেটর ব্যবহার করা যা একটি বৃহত্তর বীজের জন্য অনুমতি দেয়। জাভা এমন SecureRandomক্লাস সরবরাহ করে যা byte[]কার্যত সীমাহীন আকারের অ্যারে দিয়ে সূচনা করা যেতে পারে । তারপরে আপনি টাস্কটি শেষ SecureRandomকরার Collections.shuffleজন্য একটি উদাহরণ দিয়ে যেতে পারেন:

byte seed[] = new byte[...];
Random rnd = new SecureRandom(seed);
Collections.shuffle(deck, rnd);

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

2
@ সেরজআর্ডোভিচ হ্যাঁ, জাভা ডকুমেন্টেশন অনুসারে, সিকিউরআরডম অবজেক্টে যে কোনও বীজ উপাদান পাস হয়েছে তা অনাকাঙ্ক্ষিত হতে হবে।
dasblinkenlight

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

5
@ সেরজআরদোভিচ এর জন্য প্রয়োজনীয় ছোট বাইটের সংখ্যা ২৯ ( নোট করুন যে 29 বাইট বীজ উপাদানের ব্যবহার নীচের সীমাটি স্থাপন না করেই আপনি যে পরিমাণে সাফল্য পেতে পারেন তার তাত্ত্বিক উপরের সীমাটি সরিয়ে দেয় (একটি ক্র্যাপি আরএনজি সম্পর্কে এনপিইর মন্তব্য দেখুন যা খুব বড় বীজ নেয় এবং সমস্ত শূন্যের ক্রম তৈরি করে)।
dasblinkenlight

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

26

সাধারণভাবে, সিউডোরডম নম্বর জেনারেটর (পিআরএনজি) যদি তার রাষ্ট্রের দৈর্ঘ্য 226 বিটের চেয়ে কম হয় তবে 52-আইটেমের তালিকার সমস্ত অনুক্রমের মধ্যে থেকে চয়ন করতে পারে না।

java.util.Random2 48 এর মডুলাস সহ একটি অ্যালগরিদম প্রয়োগ করে ; সুতরাং এর রাষ্ট্রের দৈর্ঘ্য কেবল 48 বিট, আমি উল্লেখ করা 226 বিটের চেয়ে অনেক কম। আপনার বড় আর একটি দৈর্ঘ্যের পিআরএনজি ব্যবহার করতে হবে - বিশেষত, 52 টি কালচারাল বা তার চেয়ে বেশি এর পিরিয়ড সহ one

এলোমেলো সংখ্যা জেনারেটর সম্পর্কিত আমার নিবন্ধে "শিফলিং" দেখুন ।

এই বিবেচনাটি পিআরএনজির প্রকৃতির থেকে পৃথক; এটি ক্রিপ্টোগ্রাফিক এবং ননক্রিপ্টোগ্রাফিক পিআরএনজিগুলিতে সমানভাবে প্রযোজ্য (অবশ্যই তথ্য সুরক্ষার সাথে জড়িত থাকাকালীন ননক্রিপ্টোগ্রাফিক পিআরএনজি অনুপযুক্ত)।


যদিও java.security.SecureRandomসীমাহীন দৈর্ঘ্যের SecureRandomবীজগুলিকে প্রবেশের অনুমতি দেয়, বাস্তবায়নটি অন্তর্নিহিত পিআরএনজি (যেমন, "SHA1PRNG" বা "DRBG") ব্যবহার করতে পারে। এবং এটি পিআরএনজির সময়কালের উপর (এবং কিছুটা হলেও রাষ্ট্রের দৈর্ঘ্য) উপর নির্ভর করে যে এটি 52 টি ফ্যাক্টরিয়াল অনুক্রমের মধ্যে থেকে চয়ন করতে সক্ষম কিনা। (দ্রষ্টব্য যে আমি "রাষ্ট্রের দৈর্ঘ্য" সংজ্ঞায়িত করেছি যে " একটি পিআরএনজি সেই বীজকে সংক্ষিপ্ত বা সংকুচিত না করে তার রাজ্য সূচনা করতে নিতে পারে" সর্বাধিক আকারের বীজ )।


18

আমাকে আগেই ক্ষমা চাইতে দাও, কারণ এটি বুঝতে কিছুটা শক্ত ...

প্রথমত, আপনি ইতিমধ্যে জানেন যে java.util.Randomএটি একেবারে এলোমেলো নয়। এটি বীজ থেকে নিখুঁতভাবে অনুমানযোগ্য উপায়ে সিকোয়েন্স তৈরি করে। আপনি সম্পূর্ণরূপে সঠিক যে বীজটি কেবলমাত্র 64 বিট দীর্ঘ, এটি কেবল 2 2 64 বিভিন্ন সিকোয়েন্স তৈরি করতে পারে। আপনি একরকম 64 বাস্তব র্যান্ডম বিট তৈরী করা এবং একটি বীজ নির্বাচন করতে তাদের ব্যবহার করতে হলে, আপনি যে বীজ ব্যবহার করতে পারে এলোমেলোভাবে মধ্যে নির্বাচন করতে সব 52 এর! সমান সম্ভাবনা সহ সম্ভাব্য ক্রম।

তবে, যতক্ষণ না আপনি 2 2 sequ 64 সিকুয়েন্স তৈরি করতে যাচ্ছেন না, ততক্ষণ এই সত্যটির কোনও ফলস্বরূপ নয়, যতক্ষণ না 2 ^ 64 ক্রমগুলি তৈরি করতে পারে সে সম্পর্কে 'বিশেষ' বা 'উল্লেখযোগ্যভাবে বিশেষ' কিছুই নেই as ।

বলুন আপনার কাছে আরও অনেক ভাল পিআরএনজি ছিল যা 1000 বিট বীজ ব্যবহার করেছিল। কল্পনা করুন আপনার এটিকে আরম্ভ করার দুটি উপায় রয়েছে - একটি উপায় এটি পুরো বীজটি ব্যবহার করে আরম্ভ করবে এবং এক উপায়ে বীজটিকে আরম্ভ করার আগে 64৪ বিট করে হ্যাশ করবে।

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

বিকল্পভাবে, কল্পনা করুন যে Randomশ্রেণীর 2 ^ 64 ক্রমগুলির একটি অ্যারে ছিল যা সুদূর অতীতে কোনও সময়ে সম্পূর্ণ এবং এলোমেলোভাবে নির্বাচিত হয়েছিল এবং বীজটি এই অ্যারেতে কেবল একটি সূচক ছিল।

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

অবশ্যই, ক্রিপ্টোগ্রাফিক উদ্দেশ্যে, একটি bit৪ বিট বীজ কেবল পর্যাপ্ত নয়, কারণ একই বীজ দু'বার ব্যবহার করার জন্য একটি সিস্টেম পাওয়া গণনাযোগ্যভাবে সম্ভাব্য।

সম্পাদনা করুন:

উপরের সমস্তটি সঠিক হওয়া সত্ত্বেও আমার এটিকে যুক্ত করা উচিত, প্রকৃত বাস্তবায়নটি java.util.Randomদুর্দান্ত নয়। আপনি যদি কোনও কার্ড গেমটি লিখছেন, তবে সম্ভবত MessageDigestSHA-256 হ্যাশ উৎপন্ন করতে API টি ব্যবহার করুন এবং ডিকগুলি সাফল্যের "MyGameName"+System.currentTimeMillis()জন্য এই বিটগুলি ব্যবহার করুন। উপরোক্ত যুক্তি অনুসারে, যতক্ষণ না আপনার ব্যবহারকারীরা সত্যিই জুয়া খেলছেন না, currentTimeMillisততক্ষণ আপনাকে চিন্তিত হওয়ার দরকার নেই যে দীর্ঘক্ষণ ফিরে আসে। আপনার ব্যবহারকারীরা যদি সত্যিই জুয়া খেলেন তবে SecureRandomকোনও বীজ ছাড়াই ব্যবহার করুন ।


6
@ থারস্টেনস, আপনি কীভাবে এমন কোনও পরীক্ষা লিখতে পারেন যা নির্ধারণ করতে পারে যে কার্ডের সংমিশ্রণগুলি কখনই সামনে আসতে পারে না?
ম্যাট টিমারম্যানস

2
বেশ কয়েকটি র্যান্ডম সংখ্যার টেস্ট স্যুইট রয়েছে যেমন জর্জ মার্সাগলিয়া থেকে ডায়ার্ড বা পিয়ের এল'ইকায়ার / রিচার্ড সিমার্ডের টেস্ট ইউ01 যা এলোমেলো আউটপুটটিতে সহজেই পরিসংখ্যানগত ব্যঙ্গতন্ত্র খুঁজে পায়। কার্ড যাচাইয়ের জন্য আপনি দুটি স্কোয়ার ব্যবহার করতে পারেন। আপনি কার্ড অর্ডার নির্ধারণ করুন। প্রথম বর্গক্ষেত্রে প্রথম দুটি কার্ডের এক্সওয়াই জুটির অবস্থান প্রদর্শন করে: এক্স হিসাবে প্রথম কার্ড এবং y হিসাবে দ্বিতীয় কার্ডের পার্থক্য (!) অবস্থান (-26-25)। দ্বিতীয় স্কোয়ারে ২ য় / তৃতীয় এবং ২ য় / ৩ য় তুলনামূলক (-25-25) কার্ড রয়েছে। এটি যদি আপনি কিছু সময়ের জন্য চালান তবে এটি আপনার বিতরণে অবিলম্বে ফাঁক এবং ক্লাস্টারগুলি দেখায় show
থারস্টেন এস।

4
ঠিক আছে, এটি আপনি যে পরীক্ষাটি লিখেছিলেন তা নয়, তবে এটি প্রয়োগও হয় না। আপনি কেন ধরে নিয়েছেন যে বিতরণে ফাঁক এবং গুচ্ছ রয়েছে যা এই ধরনের পরীক্ষাগুলি উদঘাটন করবে? এটি ইঙ্গিত হিসাবে "PRNG বাস্তবায়নে একটি নির্দিষ্ট দুর্বলতা" বোঝায়, এবং সম্ভাব্য বীজের সংখ্যার সাথে কিছুই করার নেই। এই জাতীয় পরীক্ষাগুলির এমনকি আপনার জেনারেটরটি পুনরায় পুনঃস্থাপনের প্রয়োজন হয় না। আমি শুরুতে সতর্ক করে দিয়েছিলাম যে এটি বোঝা শক্ত।
ম্যাট টিমমারম্যানস

3
@ThorstenS। এই পরীক্ষাগুলি স্যুটগুলি একেবারে নির্ধারণ করবে না যে আপনার উত্স একটি 64-বিট-বীজযুক্ত ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত PRNG বা একটি সত্য আরএনজি কিনা। (পিআরএনজিগুলির পরীক্ষা করা হ'ল, সর্বোপরি স্যুটগুলি কীসের জন্য)
স্নেফটেল

1
@ থারস্টেনস .: কার্ডের আসল ডেকে, সংখ্যক সংখ্যক সমন্বয় কখনই আসবে না। আপনি কেবল জানেন না সেগুলি কোনটি। অর্ধ-শালীন পিআরএনজির জন্য এটি সমান - যদি আপনি পরীক্ষা করতে পারেন যে প্রদত্ত আউটপুট ক্রমটি দীর্ঘকাল তার চিত্রে রয়েছে কিনা, এটি PRNG এর ত্রুটি। হাস্যকরভাবে বিশাল রাষ্ট্র / পিরিয়ডের মতো 52! প্রয়োজন হয় না; 128-বিট যথেষ্ট হবে।
আর .. গীটহাব বন্ধ করুন ICE

10

আমি এই নিয়ে কিছুটা ভিন্ন কথা বলছি। আপনি ঠিক আপনার অনুমানের উপরে রয়েছেন - আপনার পিআরএনজি সমস্ত 52 টি হিট করতে সক্ষম হবে না! সম্ভাবনার।

প্রশ্নটি: আপনার কার্ড গেমটির স্কেল কী?

আপনি যদি একটি সাধারণ ক্লন্ডিকে স্টাইলের গেমটি তৈরি করেন? তাহলে আপনার অবশ্যই সমস্ত 52 এর দরকার নেই ! সম্ভাবনার। পরিবর্তে, এটি এর মতো দেখুন: একজন খেলোয়াড়ের 18 কুইন্টিলিয়ন স্বতন্ত্র গেম থাকবে। এমনকি 'জন্মদিনের সমস্যা' হিসাবে অ্যাকাউন্টিং করেও, তারা প্রথম নকল খেলতে যাওয়ার আগে তাদের কয়েক বিলিয়ন হাত খেলতে হবে।

আপনি যদি একটি মন্টে-কার্লো সিমুলেশন তৈরি করছেন? তাহলে আপনি সম্ভবত ঠিক আছেন । পিআরএনজিতে 'পি' এর কারণে আপনাকে নিদর্শনগুলি নিয়ে কাজ করতে হতে পারে, তবে আপনি সম্ভবত কম বীজের জায়গার কারণে সমস্যার মধ্যে পড়তে যাচ্ছেন না (আবার, আপনি অনন্য সম্ভাবনার পঞ্চম দিকে তাকিয়ে যাচ্ছেন।) অন ফ্লিপ সাইড, যদি আপনি বড় পুনরাবৃত্তি গণনা নিয়ে কাজ করছেন, তবে হ্যাঁ, আপনার কম বীজ স্থানটি একটি চুক্তি-ব্রেকার হতে পারে।

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


9

সংক্ষিপ্ত সমাধান যা মূলত ড্যাসব্লিংকনলাইটের সমান:

// Java 7
SecureRandom random = new SecureRandom();
// Java 8
SecureRandom random = SecureRandom.getInstanceStrong();

Collections.shuffle(deck, random);

অভ্যন্তরীণ অবস্থা সম্পর্কে আপনার চিন্তা করার দরকার নেই। দীর্ঘ ব্যাখ্যা কেন:

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

এই ইনপুট (!) যা এখনও উদ্দীপক চিহ্ন থাকতে পারে একটি ক্রিপ্টোগ্রাফিক শক্তিশালী হ্যাশ খাওয়ানো হয় যা সেই চিহ্নগুলি সরিয়ে দেয়। এই কারণেই সেই সিএসপিআরএনজি ব্যবহার করা হয়, those নম্বরগুলি তৈরি করার জন্য নয়! SecureRandomএকটি পাল্টা যা কতগুলি বিট ব্যবহার করা হয় (ট্রেস হয়েছে getBytes(), getLong()এবং ইত্যাদি) এক্সট্রা ড্রিংক SecureRandomএনট্রপি বিটের সাথে যখন প্রয়োজন

সংক্ষেপে: কেবল আপত্তিগুলি ভুলে যান এবং SecureRandomসত্যিকারের এলোমেলো সংখ্যা জেনারেটর হিসাবে ব্যবহার করুন।


4

যদি আপনি সংখ্যাটিকে কেবল বিটের একটি অ্যারে হিসাবে বিবেচনা করেন (বা বাইটস) তবে সম্ভবত আপনি Random.nextBytesএই স্ট্যাক ওভারফ্লো প্রশ্নে প্রস্তাবিত (সুরক্ষিত) সমাধানগুলি ব্যবহার করতে পারেন এবং তারপরে অ্যারেটিকে ম্যাপ করে new BigInteger(byte[])


3

খুব সহজ অ্যালগরিদম হল 0 থেকে উপরের দিকে বাড়ানো পূর্ণসংখ্যার ক্রমিকায় SHA-256 প্রয়োগ করা। ("আলাদা ধারাবাহিকতা" পেতে ইচ্ছুক হলে একটি লবণ যুক্ত করা যেতে পারে can) আমরা যদি ধরে নিই যে SHA-256 এর আউটপুট 0 থেকে 2 256 - 1 এর মধ্যে সমানভাবে বিতরণকৃত পূর্ণসংখ্যার "হিসাবে ভাল" হয় তবে আমাদের জন্য যথেষ্ট এনট্রপি রয়েছে কাজ।

SHA256 (যখন একটি পূর্ণসংখ্যার হিসাবে প্রকাশ করা হয়) এর আউটপুট থেকে ক্রমবিকাশ পেতে একজনকে কেবলমাত্র এটি সিউডোকোডের মতো 52, 51, 50 ... মডুলো হ্রাস করতে হবে:

deck = [0..52]
shuffled = []
r = SHA256(i)

while deck.size > 0:
    pick = r % deck.size
    r = floor(r / deck.size)

    shuffled.append(deck[pick])
    delete deck[pick]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.