উদ্দেশ্য-সি এলোমেলো সংখ্যা তৈরি করা


741

আমি প্রধানত জাভা প্রধান, এবং আমি 0 এবং 74 এর মধ্যে সিউডো-এলোমেলো সংখ্যা উত্পন্ন করার একটি উপায় চাই Java জাভাতে আমি এই পদ্ধতিটি ব্যবহার করব:

Random.nextInt(74)

আপনি বীজ বা সত্য এলোমেলো সম্পর্কে আলোচনায় আগ্রহী নন, আপনি কীভাবে উদ্দেশ্য-সি তে একই কাজটি সম্পাদন করবেন। আমি গুগলকে ঘৃণা করেছি, এবং মনে হচ্ছে প্রচুর পরিমাণে বিভিন্ন এবং বিবাদমান বিট রয়েছে।

উত্তর:


1025

আপনার arc4random_uniform()ফাংশনটি ব্যবহার করা উচিত । এটিতে একটি উচ্চতর অ্যালগরিদম ব্যবহার করা হয় rand। এমনকি আপনার একটি বীজ সেট করার দরকার নেই।

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);

arc4randomমানুষ পৃষ্ঠা:

NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

96
arc4random_uniform(x)@ ইউডের নীচে বর্ণিত হিসাবে ব্যবহার করুন । এটি stdlib.h এও রয়েছে (OS X 10.7 এবং iOS 4.3 এর পরে) এবং এলোমেলো সংখ্যার আরও অভিন্ন বিতরণ দেয়। ব্যবহারint r = arc4random_uniform(74);
লাভাস্লাইডার

4
এনবি: আরকি 4 ব্র্যান্ডম থেকে বিতরণ খুব খারাপ হতে পারে, যদি আপনি কোনও দুর্বল পরিসীমা বেছে নেন choose দু-পাওয়ার প্রত্যাশা আমি বুঝতে পারি নি। @ ইয়ুডের সংস্করণ ব্যবহারের জন্য +1 - বৃহত্তর সংখ্যার (উদাহরণস্বরূপ 400 এর পরিসীমা) জন্য একটি লক্ষণীয় পার্থক্য তৈরি করেছে
আদম

এটি কি 32 বিট সংখ্যা তৈরি করে?
jjxtra

4
পছন্দ করুন এটি সর্বদা [0, (2 ^ 32) -1] এর মধ্যে একটি পূর্ণসংখ্যা ফেরত দেয়। এটি এমন মডুলো যা আপনার নির্দিষ্ট সংখ্যার সীমাটির উপরের সীমাটিকে সীমাবদ্ধ করে দেয়।
মোতাসিম

1
এটি 0 এবং 73 এর মধ্যে একটি এলোমেলো নম্বর দেবে না?
টম হাওয়ার্ড

424

arc4random_uniform(upper_bound)একটি ব্যাপ্তির মধ্যে একটি এলোমেলো সংখ্যা তৈরি করতে ফাংশনটি ব্যবহার করুন। নিম্নলিখিত 0 এবং 73 সমেত একটি সংখ্যা উত্পন্ন করবে।

arc4random_uniform(74)

arc4random_uniform(upper_bound)ম্যান পৃষ্ঠায় বর্ণিত মডুলো পক্ষপাত এড়ানো :

arc4random_uniform () উচ্চ_বাউন্ডের চেয়ে কম অভিন্ন বিতরণ করা এলোমেলো সংখ্যা প্রদান করবে। c c arc4random ()% উপরের_বাউন্ড '' এর মতো নির্মাণগুলির উপর arc4random_uniform () বাঞ্ছনীয় কারণ যখন উপরের চৌম্বকটি দুটির শক্তি না হয় তখন " মডুলো পক্ষপাত " এড়ানো হয়।


32
নোট করুন যে arc4random_uniform () এর জন্য আইওএস 4.3 প্রয়োজন। আপনি যদি পুরানো ডিভাইসগুলিকে সমর্থন করছেন তবে আপনার একটি চেক যুক্ত করা উচিত: #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_3 এটি যদি চেকটি ব্যর্থ হয় তবে অন্য কোনও সমাধানে ফিরে যান।
রন

6
arc4random_uniform () এর জন্য 10.7 বা তার পরেও প্রয়োজন। এটি আপনার অ্যাপ্লিকেশনটি 10.6
টিবিডাবো

@ টিবিডাবো আপনার মন্তব্যটি খুব মিথ্যা এবং বিভ্রান্তিকর। আমি কেবল আইওএস 10.3 এ আরক 4 ব্র্যান্ডম_ ইউনিফর্ম () ব্যবহার করে ক্লান্ত হয়েছি এবং কোনও সমস্যা নেই। এটির জন্য 10.7 বা তার পরে প্রয়োজন নেই
চতুর্থ

1
@ চতুর্থ আইওএস 10.7 এর মতো কোনও জিনিস নেই, এটি ম্যাকোস 10.7। আমি মন্তব্যটি লেখার পরে 5 বছরেরও বেশি সময় হয়ে গেছে এটি তখন সর্বাধিক আইওএস 5 ছিল।
টিবিডাবো

63

সি হিসাবে একই, আপনি করতে হবে

#include <time.h>
#include <stdlib.h>
...
srand(time(NULL));
int r = rand() % 74;

(ধরে নিচ্ছি আপনি 0 সহ বোঝাতে চেয়েছেন তবে 74 বাদে আপনার জাভা উদাহরণটি যা করে)

সম্পাদনা করুন: বিকল্প হিসাবে random()বা এর arc4random()জন্য নির্দ্বিধায় rand()(যা অন্যরা উল্লেখ করেছে, বেশ স্তন্যপায়ী)।


43
-1। আপনাকে এলোমেলো সংখ্যা জেনারেটর বীজ করতে হবে বা আপনি প্রতিটি সম্পাদনে সংখ্যার একই প্যাটার্ন পাবেন।
অ্যালেক্স রেনল্ডস

আমি শূন্যের চেয়ে আলাদা নম্বর থেকে কীভাবে শুরু করতে চাই?
amok

2
@ জ্যামোক: আপনি ফলাফলটি থেকে শুরু করতে চান এমন নম্বরটি আপনি যুক্ত করতে পারেন
ফ্লোরিন

2
আমি 9 নম্বর পেয়ে
চলেছি

আমি কেবল এলোমেলো () পরীক্ষা করেছি এবং এটি র্যান্ড () এর মতো একই সমস্যাটি দেখিয়েছে
লোলাআর

50

আমি ভেবেছিলাম যে আমি অনেক প্রকল্পে আমি ব্যবহার করি একটি পদ্ধতি যুক্ত করতে পারি।

- (NSInteger)randomValueBetween:(NSInteger)min and:(NSInteger)max {
    return (NSInteger)(min + arc4random_uniform(max - min + 1));
}

যদি আমি এটি অনেক ফাইলে ব্যবহার করে শেষ করি তবে আমি সাধারণত ম্যাক্রো হিসাবে ঘোষণা করি

#define RAND_FROM_TO(min, max) (min + arc4random_uniform(max - min + 1))

যেমন

NSInteger myInteger = RAND_FROM_TO(0, 74) // 0, 1, 2,..., 73, 74

দ্রষ্টব্য: কেবল iOS 4.3 / OS X v10.7 (সিংহ) এবং তারপরে


দ্বিগুণ-পরিপূরক ব্যবহার করে বাইনারি পূর্ণসংখ্যার সাথে স্থির করেও সংযোজনীয় হয়। যেমন সর্বোচ্চ - মিনিট + 1 হ'ল সর্বোচ্চ + 1 - মিনিটের পাশাপাশি 1 + সর্বোচ্চ - মিনিটের মতো।
মাইকেল মরিস

44

এটি আপনাকে 0 এবং 47 এর মধ্যে একটি ভাসমান পয়েন্ট নম্বর দেবে

float low_bound = 0;      
float high_bound = 47;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);

বা কেবল সহজভাবে

float rndValue = (((float)arc4random()/0x100000000)*47);

নিম্ন এবং উপরের উভয় আবদ্ধ এছাড়াও নেতিবাচক হতে পারে । নীচের উদাহরণ কোডটি আপনাকে -35.76 এবং +12.09 এর মধ্যে একটি এলোমেলো সংখ্যা দেয়

float low_bound = -35.76;      
float high_bound = 12.09;
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);

ফলাফলটিকে একটি বৃত্তাকার পূর্ণসংখ্যার মানে রূপান্তর করুন :

int intRndValue = (int)(rndValue + 0.5);

এইটা খারাপ. আপনি কেন ভাসা ব্যবহার করছেন, এবং দ্বিগুণ নয়? এবং যদি আপনার ভাসমান পয়েন্টের মান 0 থেকে 47 অবধি হয় তবে (int) (rndValue + 0.5) কেবলমাত্র 0.0 থেকে 0.5 থেকে 0 তে মানকে রূপান্তর করবে তবে 0.5 থেকে 1.5 পর্যন্ত মানগুলি 1 তে রূপান্তরিত হবে সুতরাং সুতরাং 0 এবং সংখ্যাগুলি 47 অন্যান্য সমস্ত সংখ্যার হিসাবে প্রায় অর্ধেক হিসাবে উপস্থিত হবে।
gnasher729

@ gnasher729 দুঃখিত আমি আপনার বক্তব্যটি দেখতে পাচ্ছি না। স্পষ্টতই যদি আপনার ডাবল নির্ভুলতার প্রয়োজন হয় তবে আপনি "ভাসমান" কে "ডাবল" দিয়ে সহজেই প্রতিস্থাপন করতে পারেন
তবিডাবো

আমি মনে করি এটি বড় বিষয় নয়। আপনার যদি arc4random () / 0x100000000) * (হাই_বাউন্ড-লো_বাউন্ড) + কম_বাউন্ডটি ফ্লোট / ডাবল রূপান্তর অপসারণ করে কেবলমাত্র পূর্ণসংখ্যার মান প্রয়োজন হয়।
টিবিডাবো

আপনি যখন এভাবে পূর্ণসংখ্যাকে ভাসমান স্থলে রূপান্তর করেন তখন আপনি পক্ষপাত পাবেন। drand48পরিবর্তে ভাসমান পয়েন্টগুলির জন্য ব্যবহার করুন ।
ফ্রাঙ্কলিন ইউ

37

র্যান্ডের (3) জন্য ম্যানুয়াল পৃষ্ঠা অনুসারে, ফাংশনগুলির র‌্যান্ড পরিবারটি এলোমেলোভাবে করা হয়েছে (3)। এটি র‌্যান্ডের নিম্ন 12 টি বিট () একটি চক্রীয় বিন্যাসের মধ্য দিয়ে যায় to একটি এলোমেলো নম্বর পেতে, কেবল স্বাক্ষরবিহীন বীজের সাথে শ্রেনডম () কল করে জেনারেটর বীজ করুন এবং তারপরে এলোমেলো () কল করুন। সুতরাং, উপরের কোডের সমতুল্য হবে

#import <stdlib.h>
#import <time.h>

srandom(time(NULL));
random() % 74;

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


7
আপনি শ্রেনডমদেবকে কল করতে পারেন () সময়কে শ্রেনডমের () পরিবর্তনের পরিবর্তে; এটি ঠিক যেমন সহজ এবং গাণিতিকভাবে আরও ভাল।
বেনজাদো

31

ব্যবহার করা ভাল arc4random_uniform। তবে এটি আইওএস ৪.৩ এর নিচে উপলভ্য নয়। ভাগ্যক্রমে আইওএস সংকলনের সময় নয়, রানটাইমের সময় এই প্রতীককে আবদ্ধ করবে (সুতরাং এটি যদি পাওয়া যায় কিনা তা পরীক্ষা করতে #if প্রিপ্রসেসর নির্দেশিকা ব্যবহার করবেন না)।

arc4random_uniformউপলভ্য কিনা তা নির্ধারণ করার সর্বোত্তম উপায় হ'ল এরকম কিছু করা:

#include <stdlib.h>

int r = 0;
if (arc4random_uniform != NULL)
    r = arc4random_uniform (74);
else
    r = (arc4random() % 74);

9
এই প্রশ্নটি অবজেক্টিভ-সি সম্পর্কে যা দেরীতে বাইন্ডিং ব্যবহার করে। সি এর বিপরীতে যা সংকলন / লিংক সময়ে বাঁধে, উদ্দেশ্য-সি রানটাইমের সময় প্রতীকগুলিকে আবদ্ধ করে, এবং এটি যে চিহ্নগুলিতে আবদ্ধ হয় সেগুলি NULL এ সেট করা হয়। আপনি যখন ঠিক বলেছেন যে এটি বৈধ সি নয়, তবে এটি অবশ্যই কার্যকর বৈধ উদ্দেশ্য-সি। আমি আমার আইফোন অ্যাপে এই সঠিক কোডটি ব্যবহার করি। [পিএস দয়া করে আপনার ডাউনটোটটি সংশোধন করতে পারেন]
AW101

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

8
অ্যাপলের মতে "... লিঙ্কারটি NUL- তে অনুপলব্ধ ফাংশনের ঠিকানা সেট করে ...", তালিকাটি দেখুন ৩.২: বিকাশকারী / অ্যাপ্লিকেশন / লাইব্রেরি / ম্যাক /# ডকুমেন্টেশন / ডেভেলপারটুলস/… । ঠিক আছে তাই এটি দুর্বলভাবে সংযুক্ত করতে হবে, তবে এটি ক্রাশ হয় না।
AW101

1
কোনও ফাংশনের ঠিকানা NULL যাচাই করা একটি পদ্ধতি যা MacOS X এবং iOS উভয় সি, সি ++ এবং উদ্দেশ্য-সি উভয় সংস্করণে ব্যবহৃত হয়েছে।
gnasher729

14

আমি আমার নিজস্ব এলোমেলো নম্বর ইউটিলিটি ক্লাসটি লিখেছিলাম যাতে আমার কাছে জাভাতে ম্যাথ.রেন্ডম () এর মতো আরও কিছু কাজ করার কিছু থাকে। এটির মাত্র দুটি ফাংশন রয়েছে এবং এটি সমস্ত সিতে তৈরি

শিরোনাম ফাইল:

//Random.h
void initRandomSeed(long firstSeed);
float nextRandomFloat();

বাস্তবায়ন ফাইল:

//Random.m
static unsigned long seed;

void initRandomSeed(long firstSeed)
{ 
    seed = firstSeed;
}

float nextRandomFloat()
{
    return (((seed= 1664525*seed + 1013904223)>>16) / (float)0x10000);
}

এটি সিউডো-এলোমেলো উত্পন্ন করার একটি দুর্দান্ত ক্লাসিক উপায়। আমার অ্যাপের প্রতিনিধিতে আমি কল করি:

#import "Random.h"

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    initRandomSeed( (long) [[NSDate date] timeIntervalSince1970] );
    //Do other initialization junk.
}

তারপরে আমি কেবল বলি:

float myRandomNumber = nextRandomFloat() * 74;

নোট করুন যে এই পদ্ধতিটি 0.0f (অন্তর্ভুক্ত) এবং 1.0f (একচেটিয়া) এর মধ্যে একটি এলোমেলো সংখ্যা প্রদান করে।


3
1. এলোমেলোভাবে তৈরি এলোমেলো সংখ্যা ফাংশন সাধারণত খুব এলোমেলো হয় না। ২. এটি একটি bit৪ বিট প্রসেসরের সম্পূর্ণ বিচ্ছিন্ন broken ৩. ১৯ 1970০ সাল থেকে এলোমেলো বীজ হিসাবে সেকেন্ড ব্যবহার করা সংখ্যাগুলি অনুমানযোগ্য করে তোলে।
gnasher729

7

ইতিমধ্যে কয়েকটি দুর্দান্ত, উচ্চারণযোগ্য উত্তর রয়েছে তবে প্রশ্নটি 0 এবং 74 এর মধ্যে একটি এলোমেলো সংখ্যা জিজ্ঞাসা করে Use

arc4random_uniform(75)


4

আইওএস 9 এবং ওএস এক্স 10.11 হিসাবে, আপনি বিভিন্ন উপায়ে এলোমেলো সংখ্যা তৈরি করতে নতুন গেমপ্লেকিট ক্লাস ব্যবহার করতে পারেন।

আপনার চয়ন করতে চারটি উত্স প্রকার রয়েছে: একটি সাধারণ এলোমেলো উত্স (নাম না দিয়ে, এটি কী করে তা বেছে নেওয়ার জন্য সিস্টেমের কাছে), লিনিয়ার কংগ্র্যাশিয়াল, এআরসি 4 এবং মের্সেন টুইস্টার। এগুলি এলোমেলো ints, ভাসমান এবং bools উত্পাদন করতে পারে।

সহজ স্তরে আপনি সিস্টেমের অন্তর্নির্মিত এলোমেলো উত্স থেকে এলোমেলো সংখ্যা তৈরি করতে পারেন:

NSInteger rand = [[GKRandomSource sharedRandom] nextInt];

এটি -2,147,483,648 এবং 2,147,483,647 এর মধ্যে একটি সংখ্যা উত্পন্ন করে। আপনি যদি 0 এবং একটি উপরের বাউন্ড (একচেটিয়া) এর মধ্যে একটি নম্বর চান তবে আপনি এটি ব্যবহার করতে চান:

NSInteger rand6 = [[GKRandomSource sharedRandom] nextIntWithUpperBound:6];

গেমপ্লেকিতে পাশের সাথে কাজ করার জন্য কিছু সুবিধাজনক নির্মাণকারী রয়েছে। উদাহরণস্বরূপ, আপনি এটির মতো একটি ছয় পক্ষের ডাই রোল করতে পারেন:

GKRandomDistribution *d6 = [GKRandomDistribution d6];
[d6 nextInt];

এছাড়াও আপনি এ জাতীয় জিনিস ব্যবহার করে এলোমেলো বিতরণকে আকার দিতে পারেন GKShuffledDistribution


মার্সেন গেম ডে এর মতো জিনিসের জন্য দ্রুত এবং সেরা যেখানে র্যান্ডম সংখ্যার উত্পন্ন গুণমান সাধারণত খুব গুরুত্বপূর্ণ হয় না।
রবার্ট ওয়াসম্যান

3

0 থেকে 99 এর মধ্যে এলোমেলো সংখ্যা তৈরি করুন:

int x = arc4random()%100;

500 এবং 1000 এর মধ্যে এলোমেলো সংখ্যা তৈরি করুন:

int x = (arc4random()%501) + 500;

1

// নিম্নলিখিত উদাহরণটি 0 এবং 73 এর মধ্যে একটি সংখ্যা উত্পন্ন করতে চলেছে।

int value;
value = (arc4random() % 74);
NSLog(@"random number: %i ", value);

//In order to generate 1 to 73, do the following:
int value1;
value1 = (arc4random() % 73) + 1;
NSLog(@"random number step 2: %i ", value1);

আউটপুট:

  • এলোমেলো সংখ্যা: 72

  • এলোমেলো সংখ্যা পদক্ষেপ 2: 52


1

গেম ডেভের জন্য র্যান্ডম তৈরি করতে এলোমেলো () ব্যবহার করুন। সম্ভবত আরক 4 ব্র্যান্ডম () ব্যবহার করার চেয়ে কমপক্ষে 5x দ্রুত। মডুলো পক্ষপাতিত্ব কোনও সমস্যা নয়, বিশেষত গেমসের জন্য, যখন এলোমেলো () এর পুরো পরিসর ব্যবহার করে র্যান্ডম তৈরি করা হয়। আগে বীজ নিশ্চিত করুন। অ্যাপডেলিগেটে শ্রান্ডমদেব () কে কল করুন। এখানে কিছু সহায়ক ফাংশন রয়েছে:

static inline int random_range(int low, int high){ return (random()%(high-low+1))+low;}
static inline CGFloat frandom(){ return (CGFloat)random()/UINT32_C(0x7FFFFFFF);}
static inline CGFloat frandom_range(CGFloat low, CGFloat high){ return (high-low)*frandom()+low;}

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