র্যান্ড () ব্যবহার করার সময় আমি কেন এই নির্দিষ্ট রঙের প্যাটার্নটি পাই?


170

আমি একটি ইমেজ ফাইল তৈরি করার চেষ্টা করেছি:

uint8_t raw_r[pixel_width][pixel_height];
uint8_t raw_g[pixel_width][pixel_height];
uint8_t raw_b[pixel_width][pixel_height];
uint8_t blue(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x+y)%rand() : ((x*y%1024)%rand())%2 ? (x-y)%rand() : rand();
}
uint8_t green(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x-y)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}
uint8_t red(uint32_t x, uint32_t y)
{
    return (rand()%2)? (y-x)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}

for (y=0; y<pixel_height; ++y)
{
    for (x=0; x<pixel_width; ++x)
    {
        raw_b[x][y]=blue(x, y);
        raw_g[x][y]=green(x, y);
        raw_r[x][y]=red(x, y);
    }
}

আমি এলোমেলো কিছু (সাদা গোলমাল) পাওয়ার আশা করছিলাম। তবে আউটপুটটি আকর্ষণীয়:

এর কারণ কি জানেন?


সম্পাদন করা

এখন এটি স্পষ্ট যে এর কোনও যোগসূত্র নেই rand()

এই কোডটিও ব্যবহার করে দেখুন:

for (x=0; x<pixel_width; ++x)
    for (y=0; y<pixel_height; ++y)
    {
        r[x][y] = (x+y);
        g[x][y] = (y-x);
        /* b[x][y] = rand()%2? x : y; */
    }


26
ক্যাস র্যান্ড ইন্ট র্যান্ড - এর দুর্দান্ত ডেমো। এটি 100%
নির্দ্বিধায়


50
@ পিএম 100: যেমন বেমস ৫৩ এর উত্তরটি খুব ভালভাবে ব্যাখ্যা করেছে, আপনি যদি নিখুঁত এলোমেলো নম্বর জেনারেটর ব্যবহার করেও আপনি একই প্যাটার্নটি পাবেন।
টনিক

13
একটি প্রশ্ন ক্ষমা করুন: যেহেতু আপনি পিক্সেল মানগুলি গণনা করতে x এবং y স্থানাঙ্কগুলি ব্যবহার করছেন, আপনি কেন এই মানগুলি স্থানাঙ্কগুলির থেকে পৃথক হওয়ার প্রত্যাশা করবেন? ছবিটি যদি অভিন্নভাবে এলোমেলো দেখায় তবে তাই আপনার প্রয়োজন হবে, তাই না?
টমাস প্যাড্রন-ম্যাকার্থি

15
পাঠ শিখেছে: এলোমেলো সংখ্যার সাথে এলোমেলো কাজ করা এলোমেলো ফলাফল দেয় না :)
হ্যাগেন ভন ইটজেন

উত্তর:


355

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

টিএল; ডিআর: আপনি যে প্যাটার্নটি দেখছেন তার অন্তর্নিহিত এলোমেলো সংখ্যা জেনারেটরের সাথে কোনও সম্পর্ক নেই এবং পরিবর্তে কেবল আপনার প্রোগ্রামটি যে সংখ্যাগুলি পরিচালনা করছে তার কারণেই এটি।

আমি আপনার নীল ফাংশনটি আঁকিব কারণ তারা সব একই রকম।

uint8_t blue(uint32_t x, uint32_t y) {
    return (rand() % 2)                  ? (x + y) % rand() :
           ((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
                                           rand();
}

প্রতিটি পিক্সেল মান তিনটি কার্যকারিতা এক থেকে নির্বাচন করা হয়নি: (x + y) % rand(), (x - y) % rand(), এবং rand();

আসুন একা এই প্রতিটি দ্বারা উত্পাদিত চিত্র দেখুন।

  • rand()

এই আপনি প্রত্যাশা করবে, শুধু শব্দ। এটিকে "চিত্র সি" কল করুন

এখানে চিত্র বর্ণনা লিখুন


  • (x + y) % rand()

এখানে আপনি পিক্সেল স্থানাঙ্কগুলি একসাথে যুক্ত করছেন এবং বাকীটি এলোমেলো সংখ্যায় ভাগ করে নিচ্ছেন। চিত্রটি যদি 1024x1024 হয় তবে যোগফলটি [0-2046] এর মধ্যে হয়। আপনি যে এলোমেলো সংখ্যাটি দিয়ে ডাইভিং করছেন সেগুলি [0, RAND_MAX] এর মধ্যে রয়েছে, যেখানে RAND_MAX কমপক্ষে 32 কে এবং কিছু সিস্টেমে 2 বিলিয়ন। অন্য কথায় 16 টির মধ্যে সেরা 1 টির সম্ভাবনা রয়েছে যে বাকীটি কেবলমাত্র নয় (x + y)। সুতরাং বেশিরভাগ অংশের জন্য এই ফাংশনটি কেবলমাত্র + x + y দিকের দিকে নীল বৃদ্ধির একটি গ্রেডিয়েন্ট তৈরি করবে।

তবে আপনি কেবল সর্বনিম্ন 8 টি বিট ব্যবহার করছেন, কারণ আপনি ফিরে আসেন uint8_t, সুতরাং আপনার 256 পিক্সেল প্রশস্ত গ্রেডিয়েন্টের স্ট্রাইপ থাকবে।

এটিকে "চিত্র এ" বলুন

এখানে চিত্র বর্ণনা লিখুন


  • (x - y) % rand()

এখানে আপনি অনুরূপ কিছু করেন তবে বিয়োগ দিয়ে। X যতক্ষণ না y এর চেয়ে বড় আপনার পূর্বের চিত্রের মতো কিছু থাকবে। কিন্তু কোথায় Y বেশী, ফলে খুব বড় সংখ্যা কারণ xএবং yস্বাক্ষরবিহীন (নেতিবাচক ফলাফল স্বাক্ষরবিহীন টাইপ এর পরিসীমা শীর্ষে চারপাশে মোড়ানো), এবং তারপর % rand()মধ্যে kicks এবং আপনি আসলে গোলমাল পেতে।

এটিকে "চিত্র বি" কল করুন

এখানে চিত্র বর্ণনা লিখুন

আপনার চূড়ান্ত চিত্রের প্রতিটি পিক্সেল ফাংশন rand() % 2এবং ব্যবহার করে এই তিনটি চিত্রের একটি থেকে নেওয়া হয়েছে ((x * y % 1024) % rand()) % 2। এর মধ্যে প্রথমটি 50% সম্ভাব্যতার সাথে বেছে নেওয়া ( rand()এটির সমস্যাগুলি এবং এর নিম্ন আদেশের বিটগুলি উপেক্ষা করে ) হিসাবে বেছে নেওয়া যেতে পারে )

এখানে rand() % 2সত্য (সাদা পিক্সেল) এর একটি ক্লোজআপ তাই চিত্র এ নির্বাচন করা হয়েছে।

এখানে চিত্র বর্ণনা লিখুন

দ্বিতীয় ফাংশনটিতে ((x * y % 1024) % rand()) % 2আবার এমন সমস্যা রয়েছে যেখানে rand()আপনি (x * y % 1024)বিভাজনিত জিনিসটির চেয়ে সাধারণত বৃহত্তর হয় যা সর্বাধিক 1023 (x*y%1024)%2হয় Then তারপরে 0 এবং 1 সমানভাবে উত্পাদিত হয় না। যে কোনও বিজোড় সংখ্যাটি যে কোনও সংখ্যার দ্বারা গুণিত করা হয় সমান। যে কোনও সমান সংখ্যার দ্বারা গুণিত যে কোনও সমান সংখ্যাটিও সমান। বিজোড় সংখ্যা দ্বারা গুণিত একটি বিজোড় সংখ্যাটিই বিজোড়, এবং %2এমনকী মানগুলি যা সময়ের তিনটি চতুর্থাংশ এমনকি সময়ের তিনটি চতুর্থাংশ উত্পাদন করে।

এখানে ((x * y % 1024) % rand()) % 2সত্য যেখানে একটি ক্লোজআপ যাতে চিত্র বি নির্বাচন করা যায়। উভয় স্থানাঙ্ক বিজোড় যেখানে এটি ঠিক নির্বাচন করছে।

এখানে চিত্র বর্ণনা লিখুন

এবং এখানে চিত্র সি নির্বাচন করা যেতে পারে তার একটি ক্লোজআপ রয়েছে:

এখানে চিত্র বর্ণনা লিখুন

অবশেষে এখানে অবস্থাগুলির সংমিশ্রণ যেখানে চিত্র বি নির্বাচিত হয়েছে:

এখানে চিত্র বর্ণনা লিখুন

এবং যেখানে চিত্র সি নির্বাচন করা হয়েছে:

এখানে চিত্র বর্ণনা লিখুন

ফলস্বরূপ সংমিশ্রণটি পড়তে পারেন:

৫০% সম্ভাব্যতার সাথে চিত্র এ থেকে পিক্সেল ব্যবহার করুন, চিত্র বি এবং চিত্র সি, বি এর মধ্যে বাকি সময় বেছে নিন যেখানে উভয় স্থানাঙ্কগুলি বিজোড়, সি যেখানে উভয়ই সমান।

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


45

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

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

ইমেজ

আপনি যদি X, y এবং z এর সাথে আর, জি এবং বি স্থানাঙ্কগুলির সমন্বয় করেন তবে এটি আপনার প্রোগ্রামের দ্বারা উত্পাদিত আউটপুটের সাথে অসাধারণ মনে হচ্ছে। আমি সন্দেহ করি যে এটি সম্ভবত এখানে মূল সমস্যা নয়, কারণ উপরে বর্ণিত অন্যান্য দিকটি সম্ভবত আরও বেশি উচ্চারণ করা হবে।

আপনি যদি উচ্চ মানের মানের এলোমেলো সংখ্যা খুঁজছেন তবে আপনাকে উচ্চ মানের মানের এলোমেলো উত্স ব্যবহার করতে হবে। সি তে, আপনি /dev/urandom/(লিনাক্সের মতো সিস্টেমে) বাইটগুলি পড়তে বিবেচনা করতে পারেন , যা মোটামুটি অভিন্ন র্যান্ডম মান দেয়। সি ++ এর মানক পাঠাগারগুলিতে এখন প্রচুর ভাল এলোমেলো-সংখ্যা প্রজন্মের রয়েছে, যদি এটি আপনার কাছে উপলব্ধ থাকে।

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