সিটিতে একটি এলোমেলো সংখ্যার সংখ্যা তৈরি করার জন্য কোনও ফাংশন আছে কি? নাকি আমাকে তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করতে হবে?
srand
: কেন একবারেই কল করুন ।
সিটিতে একটি এলোমেলো সংখ্যার সংখ্যা তৈরি করার জন্য কোনও ফাংশন আছে কি? নাকি আমাকে তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করতে হবে?
srand
: কেন একবারেই কল করুন ।
উত্তর:
দ্রষ্টব্য :
rand()
সুরক্ষার জন্য ব্যবহার করবেন না । যদি আপনার কোনও ক্রিপ্টোগ্রাফিক সুরক্ষিত নম্বর প্রয়োজন হয় তবে পরিবর্তে এই উত্তরটি দেখুন ।
#include <time.h>
#include <stdlib.h>
srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
সম্পাদনা : লিনাক্সে, আপনি এলোমেলো এবং শ্রেনডম ব্যবহার করতে পছন্দ করতে পারেন ।
time()
প্রতি সেকেন্ডে একবার পরিবর্তন হয় changes যদি আপনি time()
প্রতিটি কলের জন্য থেকে বিকাশ করেন rand()
তবে আপনি একক সেকেন্ডের সময় প্রতিটি কলের জন্য একই মান পাবেন। তবে এর বড় কারণ হ'ল এর মতো বৈশিষ্ট্য rand()
এবং ফাংশনগুলি ব্যবহারের ক্ষেত্রে সর্বাধিক পরিচিত যেখানে তারা প্রতি রানে ঠিক একবারে বদ্ধ হয়, এবং প্রতিটি কলেই নয়। অরক্ষিত বা অপ্রমাণিত বৈশিষ্ট্যগুলির সাথে "র্যান্ডমনেস" এর উপর নির্ভর করে সমস্যার দিকে পরিচালিত করে।
rand()
সাধারণত এটি হয়) এর জন্য @ ট্রাসক্রিটারের সর্বোপরি rand()
কোনও প্রভাব পড়বে না এবং সবচেয়ে খারাপ দিক থেকে জেনারেটরের জানা গুণগুলি ভঙ্গ করবে। এটি একটি গভীর বিষয়। গণিত এবং সমস্যাগুলির সর্বোত্তম ভূমিকা হিসাবে এলোমেলো সংখ্যার নথ ভল 2 অধ্যায় 3 পড়তে শুরু করুন।
srand((unsigned int)time(NULL));
rand()
ফাংশন <stdlib.h>
আয় 0 এবং এর মধ্যে একটি সিউডো-রেণ্ডম পূর্ণসংখ্যা RAND_MAX
। তুমি ব্যবহার করতে পারsrand(unsigned int seed)
একটি বীজ সেট ।
%
অপারেটরটির সাথে rand()
আলাদা পরিসীমা পেতে একসাথে ব্যবহার করা সাধারণ অভ্যাস (যদিও মনে রাখবেন যে এটি কিছুটা অভিন্নতা ছুঁড়ে দেয়)। উদাহরণ স্বরূপ:
/* random int between 0 and 19 */
int r = rand() % 20;
আপনি যদি সত্যই অভিন্নতার প্রতি যত্নশীল হন তবে আপনি এরকম কিছু করতে পারেন:
/* Returns an integer in the range [0, n).
*
* Uses rand(), and so is affected-by/affects the same seed.
*/
int randint(int n) {
if ((n - 1) == RAND_MAX) {
return rand();
} else {
// Supporting larger values for n would requires an even more
// elaborate implementation that combines multiple calls to rand()
assert (n <= RAND_MAX)
// Chop off all of the values that would cause skew...
int end = RAND_MAX / n; // truncate skew
assert (end > 0);
end *= n;
// ... and ignore results from rand() that fall above that limit.
// (Worst case the loop condition should succeed 50% of the time,
// so we can expect to bail out of this loop pretty quickly.)
int r;
while ((r = rand()) >= end);
return r % n;
}
}
%
মডুলাস অপারেটর। এটা আপনি একটি পূর্ণসংখ্যা বিভাগের বাকি দেয়, তাই x % n
সবসময় আপনার মধ্যে একটি সংখ্যা দেব 0
এবং n - 1
(দীর্ঘ হিসাবে হিসাবে x
এবং n
উভয় ইতিবাচক)। আপনি এখনও যে বিভ্রান্তিকর হলে, একটি প্রোগ্রাম যা করেছে লেখার চেষ্টা i
0 থেকে 100 পর্যন্ত গণনা এবং আউট প্রিন্ট i % n
কিছু n
আপনার পছন্দসই চেয়ে ছোট 100
বিভিন্ন প্রোগ্রামিং ভাষায় কীভাবে নিরাপদে র্যান্ডম নম্বর উত্পন্ন করা যায় সেই উদ্দেশ্যে আপনি নীচের একটি করতে চান:
randombytes
এপিআই/dev/urandom
, না /dev/random
। ওপেনএসএসএল নয় (বা অন্যান্য ব্যবহারকারী স্থান PRNGs)।উদাহরণ স্বরূপ:
#include "sodium.h"
int foo()
{
char myString[32];
uint32_t myInt;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
return 1;
}
/* myString will be an array of 32 random bytes, not null-terminated */
randombytes_buf(myString, 32);
/* myInt will be a random number between 0 and 9 */
myInt = randombytes_uniform(10);
}
randombytes_uniform()
ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত এবং নিরপেক্ষ।
sodium_init()
কিছু সময় কল করুন । আরএনজি নিয়ে চিন্তা করবেন না, এটি কার্নেলের ব্যবহার করে।
sodium_init()
যদিও এটি আমার উদাহরণের অগত্যা নয় কারণ এটি একটি গুরুত্বপূর্ণ বিশদ।
এর মাধ্যমে যেতে দিন। প্রথমে আমরা র্যান্ডমাইজার বীজ করতে srand () ফাংশন ব্যবহার করি। মূলত, কম্পিউটারটি শ্রেনড () বারণ করার জন্য সংখ্যার ভিত্তিতে এলোমেলো সংখ্যা তৈরি করতে পারে। আপনি যদি একই বীজের মান দিয়ে থাকেন তবে প্রতিবার একই র্যান্ডম সংখ্যার উত্পন্ন হবে।
অতএব, আমাদের সর্বদা পরিবর্তনশীল এমন একটি মান সহ র্যান্ডমাইজার বীজ করতে হবে। আমরা এটি সময়ের () ফাংশন সহ বর্তমান সময়ের মান খাওয়ানোর মাধ্যমে এটি করি।
এখন, যখন আমরা র্যাণ্ড () বলি, প্রতিবার একটি নতুন এলোমেলো সংখ্যা তৈরি হবে।
#include <stdio.h>
int random_number(int min_num, int max_num);
int main(void)
{
printf("Min : 1 Max : 40 %d\n", random_number(1,40));
printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
return 0;
}
int random_number(int min_num, int max_num)
{
int result = 0, low_num = 0, hi_num = 0;
if (min_num < max_num)
{
low_num = min_num;
hi_num = max_num + 1; // include max_num in output
} else {
low_num = max_num + 1; // include max_num in output
hi_num = min_num;
}
srand(time(NULL));
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
else{ low_num=max_num; hi_num=min_num+1;
2) হওয়া উচিত যখন ব্যর্থ হয় hi_num - low_num > INT_MAX
। 3) বিরল পরিস্থিতিতে মান বাদ দেয় INT_MAX > hi_num - low_num > RAND_MAX
।
hi_num = max_num + 1;
প্রবাহের বিরুদ্ধে সুরক্ষার অভাব রয়েছে।
যা stdlib
সরবরাহ করে তার চেয়ে যদি আপনার আরও ভাল মানের সিউডো এলোমেলো সংখ্যার প্রয়োজন হয় তবে মার্সেন টুইস্টারটি দেখুন । এটিও দ্রুত। নমুনা বাস্তবায়নের উদাহরণস্বরূপ, অঢেল এখানে ।
স্ট্যান্ডার্ড সি ফাংশন হয় rand()
। সলিটায়ারের জন্য কার্ডগুলি ডিল করার পক্ষে এটি যথেষ্ট ভাল তবে এটি ভয়াবহ। rand()
সংখ্যার একটি সংক্ষিপ্ত তালিকার মাধ্যমে চক্রের অনেকগুলি বাস্তবায়ন , এবং কম বিটগুলির মধ্যে সংক্ষিপ্ততর চক্র থাকে। কিছু প্রোগ্রাম যেভাবে কল করে rand()
তা ভয়াবহ এবং উত্তম বীজের গণনা srand()
করা শক্ত।
সিতে এলোমেলো সংখ্যা তৈরির সর্বোত্তম উপায় হ'ল ওপেনএসএসএল এর মতো তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করা। উদাহরণ স্বরূপ,
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>
/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;
do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}
/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}
int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}
এত কোড কেন? অন্যান্য ভাষা যেমন জাভা এবং রুবিতে এলোমেলো পূর্ণসংখ্যা বা ভাসমানগুলির জন্য ফাংশন রয়েছে। ওপেনএসএসএল কেবল এলোমেলো বাইট দেয়, তাই আমি জাভা বা রুবি কীভাবে তাদের পূর্ণসংখ্যা বা ফ্লোটে রূপান্তরিত করতে পারে তা নকল করার চেষ্টা করি।
পূর্ণসংখ্যার জন্য, আমরা মডুলোর পক্ষপাত এড়াতে চাই । মনে করুন যে আমরা কিছু এলোমেলোভাবে 4 ডিজিটের পূর্ণসংখ্যা পেয়েছি rand() % 10000
তবে rand()
কেবল 0 থেকে 32767 (মাইক্রোসফ্ট উইন্ডোজে যেমন রয়েছে) ফিরে আসতে পারি। ০৮ থেকে ২ from67 from পর্যন্ত প্রতিটি সংখ্যা 2768 থেকে 9999 পর্যন্ত প্রতিটি সংখ্যার চেয়ে প্রায়শই বেশি উপস্থিত হবে the পক্ষপাত দূর করতে আমরা rand()
মানটি 2768 এর নীচে থাকা অবস্থায় আবার চেষ্টা করতে পারি , কারণ 2768 থেকে 32767 পর্যন্ত 30000 মানগুলি 0 থেকে শুরু করে 10000 মানগুলিতে একত্রে মানচিত্রের 9999।
ফ্লোটগুলির জন্য আমরা 53 টি এলোমেলো বিট চাই, কারণ double
একটিতে 53 বিট নির্ভুলতা রয়েছে (ধরে নেওয়া এটি একটি আইইইই ডাবল)। আমরা যদি 53 টিরও বেশি বিট ব্যবহার করি তবে আমরা রাউন্ডিং পক্ষপাত পাই। কিছু প্রোগ্রামার কোডের মতো কোড লেখেন rand() / (double)RAND_MAX
, তবে rand()
উইন্ডোতে কেবল 31 বিট বা 15 টি বিট দিতে পারে।
ওপেনএসএসএল এর RAND_bytes()
বীজ নিজেই /dev/urandom
লিনাক্স পড়ে। আমাদের যদি অনেক এলোমেলো সংখ্যার প্রয়োজন হয় তবে এগুলি পড়তে খুব ধীর হবে /dev/urandom
কারণ তাদের অবশ্যই কার্নেল থেকে অনুলিপি করা উচিত। ওপেনএসএসএলকে একটি বীজ থেকে আরও এলোমেলো সংখ্যা তৈরি করার অনুমতি দেওয়া দ্রুততর।
এলোমেলো সংখ্যা সম্পর্কে আরও:
srand()
। এটি পড়তে না পারলে বর্তমান সময়, প্রক্রিয়া আইডি এবং কিছু পয়েন্টার থেকে বিটগুলি মিশ্রিত করে /dev/urandom
।float
/ এর সাথে ডিল করার জন্য অতিরিক্ত ব্যাখ্যার সাথে double
, সুতরাং আমি প্রশ্নটি int
খুব বিস্তৃত না করে এড়াতে সংখ্যায় লেগে থাকার বিষয়টি পরিষ্কার করে দিয়েছি । অন্যান্য সি প্রশ্নগুলি বিশেষভাবে float
/ double
এলোমেলো মানগুলির সাথে ডিল করে , সুতরাং আপনি নিজের উত্তরটির দ্বিতীয় ভাগটি আবার পোস্ট করতে চাইতে পারেন যেমন স্ট্যাকওভারফ্লো
যদি আপনার সিস্টেমটি arc4random
ফাংশনগুলির পরিবারকে সমর্থন করে তবে আমি স্ট্যান্ডার্ড rand
ফাংশনটি পরিবর্তে সেগুলি ব্যবহার করার পরামর্শ দেব ।
arc4random
পরিবার রয়েছে:
uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)
arc4random
একটি এলোমেলো 32-বিট স্বাক্ষরযুক্ত পূর্ণসংখ্যা প্রদান করে।
arc4random_buf
এটিকে প্যারামিটারে এলোমেলো সামগ্রী রাখে buf : void *
। সামগ্রীর পরিমাণটি bytes : size_t
প্যারামিটার দ্বারা নির্ধারিত হয় ।
arc4random_uniform
নিয়ম অনুসরণ করে এমন একটি এলোমেলো 32-বিট স্বাক্ষরিত পূর্ণসংখ্যার প্রত্যাবর্তন করে: 0 <= arc4random_uniform(limit) < limit
যেখানে সীমাটিও একটি স্বাক্ষরবিহীন 32-বিট পূর্ণসংখ্যা।
arc4random_stir
এটি অভ্যন্তরীণ এলোমেলো সংখ্যা পুলের থেকে এলোমেলোভাবে /dev/urandom
ডেটা পড়ায় এবং ডেটা পাস করে arc4random_addrandom
rand
arc4random_addrandom
arc4random_stir
এটি অভ্যন্তরীণ এলোমেলো নম্বর পুলটি পাস করা ডেটা অনুসারে ব্যবহার করতে ব্যবহৃত হয় ।
আপনার যদি এই ফাংশনগুলি না থাকে তবে আপনি ইউনিক্সে রয়েছেন তবে আপনি এই কোডটি ব্যবহার করতে পারেন:
/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */
int urandom_fd = -2;
void urandom_init() {
urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
int errsv = urandom_fd;
printf("Error opening [/dev/urandom]: %i\n", errsv);
exit(1);
}
}
unsigned long urandom() {
unsigned long buf_impl;
unsigned long *buf = &buf_impl;
if (urandom_fd == -2) {
urandom_init();
}
/* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */
read(urandom_fd, buf, sizeof(long));
return buf_impl;
}
urandom_init
ফাংশন প্রর্দশিত /dev/urandom
ডিভাইস, এবং ফাইল বর্ণনাকারী রাখে urandom_fd
।
urandom
ফাংশন মূলত একটি কল হিসাবে একই rand
, আরো নিরাপদ ব্যতীত, এবং এটি একটি ফেরৎ long
(সহজে পরিবর্তনশীল)।
তবে, /dev/urandom
কিছুটা ধীর হতে পারে, সুতরাং এটির প্রস্তাব দেওয়া হয় যে আপনি এটিকে অন্য একটি এলোমেলো সংখ্যা জেনারেটরের জন্য বীজ হিসাবে ব্যবহার করুন।
আপনার সিস্টেম একটি না থাকে /dev/urandom
, কিন্তু নেই একটি আছে /dev/random
বা অনুরূপ ফাইল, তাহলে আপনি কেবল পথ প্রেরণ পরিবর্তন করতে পারেন open
মধ্যে urandom_init
। কল ও API গুলি ব্যবহার করা urandom_init
এবং urandom
হয় (আমি বিশ্বাস করি) POSIX-অনুবর্তী, এবং যেমন, যদি না সব POSIX অনুবর্তী সিস্টেম বেশিরভাগ কাজ করা উচিত।
নোটস: /dev/urandom
অপর্যাপ্ত এনট্রপি উপলব্ধ থাকলে একটি পাঠ্য অবরুদ্ধ হবে না, সুতরাং এই জাতীয় পরিস্থিতিতে উত্পন্ন মানগুলি ক্রিপ্টোগ্রাফিকভাবে নিরাপত্তাহীন হতে পারে। আপনি যদি সে সম্পর্কে উদ্বিগ্ন হন তবে ব্যবহার করুন /dev/random
যা অপর্যাপ্ত এনট্রপি থাকলে সর্বদা অবরুদ্ধ হবে।
আপনি যদি অন্য কোনও সিস্টেমে থাকেন (যেমন উইন্ডোজ), তবে ব্যবহার করুন rand
বা কিছু অভ্যন্তরীণ উইন্ডোজ নির্দিষ্ট প্ল্যাটফর্ম-নির্ভর নন-পোর্টেবল এপিআই।
ফাংশন জন্য আবরণ urandom
, rand
বা arc4random
কল:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
সিটির জন্য এসটিএল বিদ্যমান নেই আপনাকে কল করতে হবে rand
, বা আরও ভাল random
,। এগুলি স্ট্যান্ডার্ড লাইব্রেরির শিরোনামে ঘোষণা করা হয় stdlib.h
। rand
POSIX, random
এটি একটি BSD spec ফাংশন।
rand
এবং এর মধ্যে পার্থক্যটি random
হ'ল random
আরও বেশি ব্যবহারযোগ্য 32-বিট এলোমেলো সংখ্যা এবং rand
সাধারণত 16-বিট নম্বর দেয়। বিএসডি ম্যানাপেজগুলি দেখায় যে এর নীচের বিটগুলি rand
চক্রীয় এবং অনুমানযোগ্য, তাই rand
অল্প সংখ্যক জন্য এটি সম্ভবত বেহুদা।
extern int rand(void);
এবং আছে extern void srand(unsigned int);
।
কটাক্ষপাত আছে ISAAC (অপ্রত্যক্ষ্যতার, শিফট, স্তূপাকার, যোগ করুন, এবং গণনা)। এটি সমানভাবে বিতরণ করা হয়েছে এবং এর দৈর্ঘ্যের গড় চক্র দৈর্ঘ্য 2 ^ 8295।
আপনার পছন্দের দুটি সংখ্যার মধ্যে একটি এলোমেলো নম্বর পাওয়ার এটি একটি ভাল উপায়।
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define randnum(min, max) \
((rand() % (int)(((max) + 1) - (min))) + (min))
int main()
{
srand(time(NULL));
printf("%d\n", randnum(1, 70));
}
প্রথম বার আউটপুট: 39
দ্বিতীয় বার আউটপুট: 61
তৃতীয় বার আউটপুট: 65
আপনি randnum
যে নাম্বারটি বেছে নিন তার পরে আপনি মানগুলি পরিবর্তন করতে পারেন এবং এটি আপনার জন্য এই দুটি সংখ্যার মধ্যে একটি এলোমেলো সংখ্যা তৈরি করবে।
আপনি ব্যবহার করতে চান rand()
। দ্রষ্টব্য ( খুব গুরুত্বপূর্ণ ): র্যান্ড ফাংশনের জন্য বীজ সেট করতে ভুলবেন না। আপনি যদি না করেন তবে আপনার এলোমেলো সংখ্যাগুলি সত্যিকারের এলোমেলো নয় । এটি খুব, খুব, খুব গুরুত্বপূর্ণ। ধন্যবাদ, আপনি সাধারণত একটি ভাল বীজ পেতে সিস্টেম টিক্স টাইমার এবং তারিখের কিছু সংমিশ্রণ ব্যবহার করতে পারেন।
এফডব্লিউআইডাব্লু, উত্তরটি হ্যাঁ, একটি stdlib.h
ফাংশন বলা হয় rand
; এই ফাংশনটি প্রাথমিকভাবে গতি এবং বিতরণের জন্য সুর করা হয়, অনাকাঙ্ক্ষিততার জন্য নয়। বিভিন্ন ভাষা এবং ফ্রেমওয়ার্কের জন্য প্রায় সমস্ত অন্তর্নির্মিত র্যান্ডম ফাংশনগুলি ডিফল্টরূপে এই ফাংশনটি ব্যবহার করে। এছাড়াও "ক্রিপ্টোগ্রাফিক" র্যান্ডম সংখ্যার জেনারেটর রয়েছে যা খুব কম অনুমানযোগ্য তবে অনেক ধীর গতিতে চালিত হয়। এগুলি যে কোনও ধরণের সুরক্ষা-সম্পর্কিত অ্যাপ্লিকেশনটিতে ব্যবহার করা উচিত।
এটি আশা করি কেবল ব্যবহারের চেয়ে কিছুটা এলোমেলো srand(time(NULL))
।
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));
srand(rand());
for (int i = 0; i < 10; i++)
printf("%d\n", rand());
}
ঠিক আছে, এসটিএল হ'ল সি ++, সি নয়, তাই আপনি কী চান তা আমি জানি না। আপনি যদি সি চান তবে তবে এর কার্য rand()
ও srand()
কার্যকারিতা রয়েছে:
int rand(void);
void srand(unsigned seed);
এটি উভয়ই এএনএসআই সি এর অংশ রয়েছে এখানে আরও রয়েছে random()
:
long random(void);
তবে আমি যতদূর বলতে পারি, random()
এএনএসআই সি স্ট্যান্ডার্ড নয় তৃতীয় পক্ষের গ্রন্থাগারটি কোনও খারাপ ধারণা নাও হতে পারে, তবে এটি সমস্ত নির্ভর করে যে আপনার সংখ্যা কতটা এলোমেলোভাবে তৈরি করতে হবে তা নির্ভর করে।
সি প্রোগ্রাম 9 এবং 50 এর মধ্যে এলোমেলো সংখ্যা তৈরি করতে
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int lowerLimit = 10, upperLimit = 50;
int r = lowerLimit + rand() % (upperLimit - lowerLimit);
printf("%d", r);
}
সাধারণভাবে আমরা লোয়ারলিমিট এবং আপারলিমিট -১ এর মধ্যে একটি এলোমেলো সংখ্যা তৈরি করতে পারি
যেমন লোয়ারলিমিট অন্তর্ভুক্ত বা r say [লোয়ারলিমিট, আপারলিমিট) বলুন
rand()
এলোমেলো সংখ্যা উত্পন্ন করার সবচেয়ে সুবিধাজনক উপায়।
আপনি যে কোনও অনলাইন পরিষেবা যেমন র্যান্ডম.org থেকেও র্যান্ডম নম্বর পেতে পারেন।
#include <stdio.h>
#include <stdlib.h>
void main()
{
int visited[100];
int randValue, a, b, vindex = 0;
randValue = (rand() % 100) + 1;
while (vindex < 100) {
for (b = 0; b < vindex; b++) {
if (visited[b] == randValue) {
randValue = (rand() % 100) + 1;
b = 0;
}
}
visited[vindex++] = randValue;
}
for (a = 0; a < 100; a++)
printf("%d ", visited[a]);
}
#include <stdio.h>
#include <dos.h>
int random(int range);
int main(void)
{
printf("%d", random(10));
return 0;
}
int random(int range)
{
struct time t;
int r;
gettime(&t);
r = t.ti_sec % range;
return r;
}
আধুনিক x86_64 সিপিইউতে আপনি হার্ডওয়্যার এলোমেলো নম্বর জেনারেটর এর মাধ্যমে ব্যবহার করতে পারেন _rdrand64_step()
উদাহরণ কোড:
#include <immintrin.h>
uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
// Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//generate number in range [min,max)
int random(int min, int max){
int number = min + rand() % (max - min);
return number;
}
//Driver code
int main(){
srand(time(NULL));
for(int i = 1; i <= 10; i++){
printf("%d\t", random(10, 100));
}
return 0;
}
কেন rand()
নির্দিষ্ট প্রদত্ত পরিসরে অবিচ্ছিন্নভাবে বিতরণ করা এলোমেলো সংখ্যার উত্পাদনের জন্য একটি সঠিক ধারণা শুনে আমি আউটপুটটি আসলে কী পরিমাণ স্কুড তা একবার দেখে নেওয়ার সিদ্ধান্ত নিয়েছি। আমার পরীক্ষার কেসটি ফর্স ডাইস নিক্ষেপ করা হয়েছিল। সি কোডটি এখানে:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
int dice[6];
for (i = 0; i < 6; i++)
dice[i] = 0;
srand(time(NULL));
const int TOTAL = 10000000;
for (i = 0; i < TOTAL; i++)
dice[(rand() % 6)] += 1;
double pers = 0.0, tpers = 0.0;
for (i = 0; i < 6; i++) {
pers = (dice[i] * 100.0) / TOTAL;
printf("\t%1d %5.2f%%\n", dice[i], pers);
tpers += pers;
}
printf("\ttotal: %6.2f%%\n", tpers);
}
এবং তার ফলাফল এখানে:
$ gcc -o t3 t3.c
$ ./t3
1666598 16.67%
1668630 16.69%
1667682 16.68%
1666049 16.66%
1665948 16.66%
1665093 16.65%
total: 100.00%
$ ./t3
1667634 16.68%
1665914 16.66%
1665542 16.66%
1667828 16.68%
1663649 16.64%
1669433 16.69%
total: 100.00%
আপনার র্যান্ডম সংখ্যার জন্য আপনাকে কত ইউনিফর্মের প্রয়োজন তা আমি জানি না, তবে উপরের অংশটি বেশিরভাগ প্রয়োজনের জন্য যথেষ্ট অভিন্ন uniform
সম্পাদনা করুন: PRNG এর চেয়ে ভাল কিছু দিয়ে আরম্ভ করা ভাল ধারণা হবে time(NULL)
।
আমার সাম্প্রতিক অ্যাপ্লিকেশনটিতে সিউডো এলোমেলো নম্বর জেনারেটর নিয়ে আমার একটি গুরুতর সমস্যা ছিল: আমি পুনরুত্থিতভাবে আমার সি প্রোগ্রামটিকে পাইটোন স্ক্রিপ্টের মাধ্যমে কল করেছি এবং আমি নিম্নলিখিত কোডটি বীজ হিসাবে ব্যবহার করছি:
srand(time(NULL))
তবে, যেহেতু:
man srand
);time
হয় তবে প্রতিবার একই মানটি ফিরিয়ে দেবে।আমার প্রোগ্রাম সংখ্যার একই ক্রম উত্পন্ন। এই সমস্যাটি সমাধান করার জন্য আপনি 3 টি জিনিস করতে পারেন:
রান নিয়ে পরিবর্তিত কিছু অন্যান্য তথ্যের সাথে টাইম আউটপুট মেশান (আমার অ্যাপ্লিকেশনটিতে, আউটপুট নাম):
srand(time(NULL) | getHashOfString(outputName))
সময়ের রেজোলিউশন বাড়ান। আমার প্ল্যাটফর্মে, clock_gettime
উপলব্ধ ছিল, তাই আমি এটি ব্যবহার:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec);
উভয় পদ্ধতি একসাথে ব্যবহার করুন:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec | getHashOfString(outputName));
অপশন 3 আপনাকে সেরা বীজের এলোমেলোতা নিশ্চিত করে (যতদূর আমি জানি), তবে এটি কেবল খুব দ্রুত প্রয়োগের ক্ষেত্রেই পার্থক্য তৈরি করতে পারে। আমার মতে বিকল্প 2 একটি নিরাপদ বাজি।
rand()
ক্রিপ্টোগ্রাফিক ডেটার জন্য ব্যবহার করা উচিত নয়, আমি সম্মত। কমপক্ষে আমার জন্য, আমার অ্যাপ্লিকেশনটিতে ক্রিপ্টোগ্রাফিক ডেটা জড়িত ছিল না, তাই আমার জন্য এটি দেওয়া পদ্ধতিটি ঠিক ছিল।
rand()
এখানে সমস্ত লোকের পরামর্শ সত্ত্বেও , আপনি না rand()
থাকলে আপনি ব্যবহার করতে চান না ! rand()
উত্পাদিত এলোমেলো সংখ্যা প্রায়শই খুব খারাপ হয়। লিনাক্স ম্যান পৃষ্ঠা থেকে উদ্ধৃতি দিতে:
লিনাক্স সি লাইব্রেরির সংস্করণগুলিতে
rand()
এবংsrand()
একই র্যান্ডম সংখ্যা জেনারেটরটি ব্যবহার করেrandom(3)
এবংsrandom(3)
তাই নিম্ন-অর্ডার বিটগুলি উচ্চ-অর্ডার বিটের মতো এলোমেলো হওয়া উচিত। তবে, পুরানো র্যান্ড () বাস্তবায়ন এবং বিভিন্ন সিস্টেমে বর্তমান প্রয়োগে, নিম্ন-অর্ডার বিটগুলি উচ্চ-অর্ডার বিটের চেয়ে অনেক কম এলোমেলো । যখন ভাল এলোমেলো প্রয়োজন হয় তখন পোর্টেবল হবার উদ্দেশ্যে অ্যাপ্লিকেশনগুলিতে এই ফাংশনটি ব্যবহার করবেন না। ( পরিবর্তে ব্যবহারrandom(3)
করুন। )
বহনযোগ্যতা সম্পর্কে, random()
বেশ কিছু সময়ের জন্য পসিক্স স্ট্যান্ডার্ড দ্বারাও সংজ্ঞায়িত করা হয়েছে। rand()
এটি পুরানো, এটি ইতিমধ্যে প্রথম পসিক্স.১ স্পেসে random()
প্রকাশিত হয়েছিল (আইইইই ધોરણ 1003.1-1988 ), যেখানে প্রথম পসিক্স ১.২-২০০১ (আইআইইই ધોરણ 1003.1-2001) প্রকাশিত হয়েছে, তবুও বর্তমান পসিএক্স স্ট্যান্ডার্ড ইতিমধ্যে পসিএক্স .1-2008 (আইইইই স্ট্যান্ড 1003.1-2008), যা মাত্র এক বছর আগে একটি আপডেট পেয়েছিল (আইইইই ધોરણ 1003.1-2008, 2016 সংস্করণ)। সুতরাং আমি বিবেচনা করবেrandom()
খুব বহনযোগ্য হিসাবে ।
POSIX.1-2-2001 এছাড়াও lrand48()
এবং mrand48()
ফাংশন চালু করেছে , এখানে দেখুন :
ফাংশনগুলির এই পরিবারটি লিনিয়ার কংগ্রোভেনশিয়াল অ্যালগরিদম এবং 48-বিট পূর্ণসংখ্যার গাণিতিক ব্যবহার করে সিউডো-এলোমেলো সংখ্যা তৈরি করবে।
এবং বেশ ভাল সিউডো এলোমেলো উত্স হ'ল arc4random()
বহু সিস্টেমে উপলব্ধ ফাংশন। কোনও অফিসিয়াল স্ট্যান্ডার্ডের অংশ নয়, ১৯৯ BS সালের দিকে বিএসডি-তে উপস্থিত হয়েছিল তবে আপনি এটি লিনাক্স এবং ম্যাকোস / আইওএসের মতো সিস্টেমে খুঁজে পেতে পারেন।
random()
উইন্ডোজে নেই।
rand()
কারণ এটি সি স্ট্যান্ডার্ড দ্বারাও প্রয়োজনীয়। অন্য যে কোনও কিছুর জন্য আপনার কেবল উইন্ডোজের জন্য একটি বিশেষ সমাধান প্রয়োজন, ঠিক যথারীতি। #ifdef _WIN32
ক্রস প্ল্যাটফর্ম কোডে আপনি প্রায়শই দেখতে পাবেন এমন বাক্যাংশ যা উইন্ডোজ সমর্থন করতে চায় পাশাপাশি সাধারণত একটি সমাধান রয়েছে যা সমস্ত সিস্টেমের সাথে কাজ করে এবং এটি কেবল উইন্ডোজের জন্য প্রয়োজনীয়।
লিনাক্স সি অ্যাপ্লিকেশনগুলির জন্য:
এটি আমার সি কোড অনুশীলনগুলি অনুসরণ করে এবং যে কোনও আকারের এলোমেলো বাফার প্রদান করে (সঠিক রিটার্ন কোডগুলি সহ) above urandom_open()
আপনার প্রোগ্রামের শুরুতে একবার কল করতে ভুলবেন না ।
int gUrandomFd = -1;
int urandom_open(void)
{
if (gUrandomFd == -1) {
gUrandomFd = open("/dev/urandom", O_RDONLY);
}
if (gUrandomFd == -1) {
fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
errno, strerror(errno));
return -1;
} else {
return 0;
}
}
void urandom_close(void)
{
close(gUrandomFd);
gUrandomFd = -1;
}
//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
int ret = 0; // Return value
if (gUrandomFd == -1) {
fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
return -1;
}
ret = read(gUrandomFd, buf, size);
if (ret != size) {
fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
ret, size);
return -1;
} else {
return 0;
}
}
আমার ন্যূনতম সমাধানটি এলোমেলো সংখ্যার জন্য কাজ করা উচিত [min, max)
। srand(time(NULL))
ফাংশন শুরু করার আগে ব্যবহার করুন ।
int range_rand(int min_num, int max_num) {
if (min_num >= max_num) {
fprintf(stderr, "min_num is greater or equal than max_num!\n");
}
return min_num + (rand() % (max_num - min_num));
}
এটি চেষ্টা করুন, আমি ইতিমধ্যে উপরে উল্লিখিত কয়েকটি ধারণা থেকে এটি একসাথে রেখেছি:
/*
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
*/
int random(int max) {
srand((unsigned) time(NULL));
return (rand() % max) + 1;
}
srand()
প্রত্যেক সময় আপনি কল করতে চান rand()
একটি ভয়ানক ধারণা। যেহেতু এই ক্রিয়াকলাপটিকে দ্রুত কল করা সেকেন্ডেtime()
একটি মান ফেরত দেয় একই "এলোমেলো" মানটি ফিরে আসবে।
random()
ফাংশনে বিভ্রান্ত হবে ।