क्या C में एक यादृच्छिक int संख्या उत्पन्न करने के लिए एक फ़ंक्शन है? या मुझे किसी तीसरे पक्ष के पुस्तकालय का उपयोग करना होगा?
srand
: क्यों केवल एक बार इसे कहते ।
क्या C में एक यादृच्छिक int संख्या उत्पन्न करने के लिए एक फ़ंक्शन है? या मुझे किसी तीसरे पक्ष के पुस्तकालय का उपयोग करना होगा?
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.
संपादित करें : लिनक्स पर, आप यादृच्छिक और srandom का उपयोग करना पसंद कर सकते हैं ।
time()
केवल एक बार प्रति सेकंड बदलता है। यदि आप 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()
कुछ बिंदु पर कॉल करें । RNG के बारे में चिंता न करें, यह कर्नेल का उपयोग करता है।
sodium_init()
हालांकि यह मेरे उदाहरण का जरूरी हिस्सा नहीं है क्योंकि यह एक महत्वपूर्ण विवरण है।
इससे गुज़रते हैं। सबसे पहले हम रैंडमाइज़र को सीड करने के लिए सरंड () फ़ंक्शन का उपयोग करते हैं। मूल रूप से, कंप्यूटर उस संख्या के आधार पर यादृच्छिक संख्या उत्पन्न कर सकता है जिसे श्रंद () को खिलाया जाता है। यदि आप एक ही बीज मूल्य देते हैं, तो हर बार एक ही यादृच्छिक संख्या उत्पन्न होगी।
इसलिए, हमें रैंडमाइज़र को एक ऐसे मान के साथ बीजना होगा जो हमेशा बदलता रहता है। हम इसे वर्तमान समय के मूल्य () फ़ंक्शन के साथ खिलाकर करते हैं।
अब, जब हम रैंड () कहते हैं, तो हर बार एक नया रैंडम नंबर तैयार किया जाएगा।
#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
प्रदान करता है, तो मेर्सेन ट्विस्टर देखें । यह तेज है, भी। उदाहरण के लिए नमूना कार्यान्वयन बहुतायत से हैं ।
मानक C फ़ंक्शन है 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;
}
इतना कोड क्यों? जावा और रूबी जैसी अन्य भाषाओं में यादृच्छिक पूर्णांक या फ़्लोट्स के लिए फ़ंक्शन हैं। ओपनएसएसएल केवल यादृच्छिक बाइट्स देता है, इसलिए मैं नकल करने की कोशिश करता हूं कि जावा या रूबी उन्हें पूर्णांक या फ़्लोट में कैसे बदल देगा।
पूर्णांक के लिए, हम modulo पूर्वाग्रह से बचना चाहते हैं । मान लीजिए कि हमें कुछ यादृच्छिक 4 अंकीय पूर्णांक मिले हैं rand() % 10000
, लेकिन rand()
केवल 0 से 32767 पर वापस आ सकते हैं (जैसा कि यह माइक्रोसॉफ्ट विंडोज में है)। प्रत्येक संख्या 0 से 2767 तक प्रत्येक संख्या 2768 से 9999 तक अधिक बार दिखाई देगी। पूर्वाग्रह को दूर करने के लिए, हम पुन: प्रयास कर सकते हैं, rand()
जबकि मूल्य 2768 से नीचे है, क्योंकि 30068 मान 2768 से 32767 मानचित्र पर समान रूप से 0 से 10000 मान पर है। 9999।
फ़्लोट्स के लिए, हमें 53 यादृच्छिक बिट्स चाहिए, क्योंकि double
53 बिट्स ऑफ प्रिसेंस (यह एक IEEE डबल है) मानते हुए। यदि हम 53 से अधिक बिट्स का उपयोग करते हैं, तो हम गोल पूर्वाग्रह प्राप्त करते हैं। कुछ प्रोग्रामर जैसे कोड लिखते हैं rand() / (double)RAND_MAX
, लेकिन rand()
केवल 31 बिट्स या विंडोज में केवल 15 बिट्स वापस कर सकते हैं।
ओपनएसएसएल के RAND_bytes()
बीज स्वयं, शायद /dev/urandom
लिनक्स में पढ़कर । यदि हमें कई यादृच्छिक संख्याओं की आवश्यकता है, तो उन सभी से पढ़ना बहुत धीमा होगा /dev/urandom
, क्योंकि उन्हें कर्नेल से कॉपी किया जाना चाहिए। ओपनएसएसएल को एक बीज से अधिक यादृच्छिक संख्या उत्पन्न करने की अनुमति देना तेजी से होता है।
यादृच्छिक संख्याओं के बारे में अधिक जानकारी:
srand()
। यह मौजूदा समय, प्रक्रिया आईडी और कुछ संकेत से बिट्स को मिलाता है, अगर यह नहीं पढ़ सकता है /dev/urandom
।float
/ के साथ सौदा करने के लिए एक अतिरिक्त व्याख्या के साथ एक ही थे double
, इसलिए मैंने प्रश्न को स्पष्ट कर दिया है ताकि int
इसे बहुत व्यापक बनाने से बचने के लिए संख्याओं से चिपके रहें । वहाँ अन्य सी के साथ विशेष रूप से काम कर सवाल कर रहे हैं float
/ double
यादृच्छिक मान है, तो आप निम्न प्रकार के प्रश्नों का जवाब की अपनी दूसरी छमाही repost करने के लिए चाहते हो सकता है stackoverflow.com/questions/13408990/...
यदि आपका सिस्टम 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
इसके अतिरिक्त आंतरिक यादृच्छिक संख्या पूल को यादृच्छिक बनाने के लिए डेटा को पास करता है ।
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;
}
STL C. के लिए मौजूद नहीं है। आपको कॉल करना है rand
या अभी तक बेहतर है random
। ये मानक पुस्तकालय शीर्षक में घोषित किए गए हैं stdlib.h
। rand
POSIX है, random
एक BSD कल्पना फ़ंक्शन है।
के बीच का अंतर rand
और random
वह यह है कि random
रिटर्न एक बहुत अधिक प्रयोग करने योग्य 32-बिट यादृच्छिक संख्या, और rand
एक 16-बिट संख्या दिखाता है आम तौर पर। बीएसडी मैनपेज बताते हैं कि निचले हिस्से rand
चक्रीय और अनुमानित हैं, इसलिए rand
छोटी संख्या के लिए संभावित रूप से बेकार है।
extern int rand(void);
और है extern void srand(unsigned int);
।
इसहाक पर एक नजर है (Indirection, Shift, Accumulate, Add, and Count) । समान रूप से वितरित और इसकी औसत चक्र लंबाई 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());
}
खैर, एसटीएल सी ++ है, सी नहीं, इसलिए मुझे नहीं पता कि आप क्या चाहते हैं। यदि आप C चाहते हैं, तो, कार्य rand()
और srand()
कार्य हैं:
int rand(void);
void srand(unsigned seed);
ये दोनों एएनएसआई सी का हिस्सा हैं। random()
समारोह भी है :
long random(void);
लेकिन जहाँ तक मैं बता सकता हूँ, random()
मानक ANSI C. नहीं है। एक तृतीय-पक्ष पुस्तकालय एक बुरा विचार नहीं हो सकता है, लेकिन यह सब इस बात पर निर्भर करता है कि किसी संख्या का यादृच्छिक होना जो आपको वास्तव में उत्पन्न करने की आवश्यकता है।
C 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);
}
सामान्य तौर पर हम लोअरलिमिट और अपरलिमिट -1 के बीच एक यादृच्छिक संख्या उत्पन्न कर सकते हैं
लोअर लिलिमिट समावेशी है या r L कहें [लोवलीम, अपरलीम)
rand()
यादृच्छिक संख्या उत्पन्न करने के लिए सबसे सुविधाजनक तरीका है।
आप random.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 CPU पर आप हार्डवेयर रैंडम नंबर जनरेटर का उपयोग कर सकते हैं _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%
मुझे नहीं पता कि आपको अपने रैंडम नंबरों के लिए कितनी वर्दी की जरूरत है, लेकिन ऊपर से ज्यादातर जरूरतों के लिए एक समान प्रतीत होता है।
संपादित करें: PRNG को किसी बेहतर चीज़ से शुरू करना एक अच्छा विचार होगा time(NULL)
।
मेरे हाल के आवेदन में छद्म यादृच्छिक संख्या जनरेटर के साथ एक गंभीर मुद्दा था: मैंने अपने सी प्रोग्राम को एक पाइथन स्क्रिप्ट के माध्यम से दोहराया और मैं निम्नलिखित कोड को बीज के रूप में उपयोग कर रहा था:
srand(time(NULL))
हालाँकि, चूंकि:
man srand
);time
तो हर बार समान मान लौटाएगा।मेरे कार्यक्रम ने संख्याओं का एक ही क्रम उत्पन्न किया। इस समस्या को हल करने के लिए आप 3 चीजें कर सकते हैं:
कुछ अन्य जानकारी के साथ रन टाइम मिक्स आउटपुट (मेरे आवेदन में, आउटपुट नाम):
srand(time(NULL) | getHashOfString(outputName))
मैंने अपने हैश फंक्शन के रूप में djb2 का उपयोग किया ।
समय संकल्प बढ़ाएं। मेरे मंच पर 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()
पुराना है, यह पहले से ही POSIX.1 कल्पना (IEEE Std 1003.1-1988) में random()
पहले से ही दिखाई दिया था , जबकि पहली POSIX.1-2001 (IEEE Std 1003.1-2001) में दिखाई दिया, फिर भी वर्तमान POSIX मानक पहले से POSIX.1-2008 है। (IEEE Std 1003.1-2008), जिसे एक साल पहले ही अपडेट मिला था (IEEE Std 1003.1-2008, 2016 संस्करण)। तो मैं विचार करूंगाrandom()
बहुत पोर्टेबल होना ।
POSIX.1-2001 ने भी कार्य lrand48()
और mrand48()
कार्य शुरू किए , यहां देखें :
फ़ंक्शंस का यह परिवार एक रैखिक बधाई एल्गोरिथ्म और 48-बिट पूर्णांक अंकगणितीय का उपयोग करके छद्म यादृच्छिक संख्या उत्पन्न करेगा।
और बहुत अच्छा छद्म यादृच्छिक स्रोत वह arc4random()
फ़ंक्शन है जो कई प्रणालियों पर उपलब्ध है। किसी भी आधिकारिक मानक का हिस्सा नहीं, 1997 के आसपास बीएसडी में दिखाई दिया, लेकिन आप इसे लिनक्स और मैकओएस / आईओएस जैसी प्रणालियों पर पा सकते हैं।
random()
विंडोज पर मौजूद नहीं है।
rand()
क्योंकि यह भी सी मानक द्वारा आवश्यक है। किसी और चीज के लिए, आपको विंडोज के लिए एक विशेष समाधान की आवश्यकता है, हमेशा की तरह। #ifdef _WIN32
वह वाक्यांश है जिसे आप क्रॉस-प्लेटफ़ॉर्म कोड में सबसे अधिक बार देखेंगे जो विंडोज के साथ-साथ समर्थन करना चाहता है आमतौर पर एक समाधान है जो सभी प्रणालियों के साथ काम करता है और एक जो केवल विंडोज के लिए आवश्यक है।
लिनक्स सी अनुप्रयोगों के लिए:
यह ऊपर दिए गए उत्तर से मेरा पुन: कोडित कोड है जो मेरी सी कोड प्रथाओं का अनुसरण करता है और किसी भी आकार का एक यादृच्छिक बफर (उचित रिटर्न कोड आदि के साथ) देता है। 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()
फ़ंक्शन के साथ भ्रमित हो जाएगा ।