रैंडम फ्लोट नंबर जनरेशन


271

मैं C ++ में यादृच्छिक फ़्लोट कैसे उत्पन्न करता हूं?

मुझे लगा कि मैं पूर्णांक रैंड ले सकता हूं और इसे किसी चीज से विभाजित कर सकता हूं, क्या यह पर्याप्त होगा?


2
यह निर्भर करता है कि आप किस नंबर के लिए चाहते हैं, और कैसे यादृच्छिक। आम तौर पर रैंड () यादृच्छिकता के 15 बिट्स देगा, लेकिन झांकियों में 23 बिट सटीकता है, इसलिए यह कुछ मानों को याद नहीं करेगा।
पीट किर्कम

1
मैंने उपलब्ध सभी प्रमुख विकल्पों को शामिल करने के लिए अपने उत्तर को अपडेट कर दिया है और randomC ++ 11 में जोड़े गए शीर्ष लेख पर ध्यान केंद्रित करने के लिए मेरी पसंद को मानक दस्तावेज़ N3924: हतोत्साहित करने वाली रैंड () C ++ 14 में आगे बढ़ाया है । मैं rand()ज्यादातर ऐतिहासिक विचारों के लिए अपने जवाब में शामिल करता हूं, लेकिन विरासत आवेदन को साकार भी करता है।
शैफिक यघमौर

मेरे उत्तर में यह शामिल है कि <random>हेडर के साथ हर बार समान संख्याओं को प्राप्त करने से कैसे बचें
Andreas DM

जवाबों:


381

rand()C ++ में छद्म यादृच्छिक संख्या उत्पन्न करने के लिए उपयोग किया जा सकता है। साथ RAND_MAXऔर थोड़ा गणित के संयोजन में , आप अपने द्वारा चुने गए किसी भी मनमाने अंतराल में यादृच्छिक संख्या उत्पन्न कर सकते हैं। यह सीखने के उद्देश्यों और खिलौना कार्यक्रमों के लिए पर्याप्त है। यदि आपको सामान्य वितरण के साथ वास्तव में यादृच्छिक संख्याओं की आवश्यकता है , तो आपको अधिक उन्नत विधि को नियोजित करना होगा।


यह समावेशी 0.0 से 1.0 तक की संख्या उत्पन्न करेगा।

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

यह कुछ मनमाने ढंग से करने के लिए 0.0 से एक नंबर उत्पन्न होगा float, X:

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

यह कुछ मनमाना से एक नंबर उत्पन्न होगा LOकुछ मनमाने ढंग से करने के लिए HI:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

ध्यान दें कि rand()फ़ंक्शन अक्सर पर्याप्त नहीं होगा यदि आपको वास्तव में यादृच्छिक संख्याओं की आवश्यकता होती है।


कॉल करने से पहले rand(), आपको कॉल करके सबसे पहले यादृच्छिक संख्या जनरेटर को "बीज" करना होगा srand()। यह आपके कार्यक्रम के चलाने के दौरान एक बार किया जाना चाहिए - हर बार जब आप कॉल करते हैं तो एक बार नहीं rand()। यह अक्सर इस तरह किया जाता है:

srand (static_cast <unsigned> (time(0)));

कॉल करने के लिए randया srandआपको करना चाहिए #include <cstdlib>

कॉल करने के लिए time, आपको करना होगा #include <ctime>


22
पहले बीज मत भूलना!
प्रात:

14
ध्यान दें कि दोनों सीमाएं समावेशी हैं।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

14
यह उत्तर भ्रामक है। इसे पिछले सप्ताह गोइंग नेटिव 2013 में कवर किया गया था; रैंड () बहुत विस्तृत विवरण के लिए हानिकारक, Channel9.msdn.com/Events/GoingNative/2013/… पर विचार किया ।
एडी मिलर

14
मुझे समझ नहीं आ रहा है कि इतने सारे लोगों ने इस जवाब को क्यों गलत ठहराया। यह गणितीय रूप से गलत है। RAND_MAX एक बहुत छोटी संख्या है (आमतौर पर 2 ^ 16)। इसका मतलब है कि फ़्लोटिंग पॉइंट के 23 बिट्स से आप केवल 15 यादृच्छिक बनाते हैं। दूसरे शायद शून्य होंगे। आपको वास्तव में कम वितरण में एक समान वितरण में यादृच्छिक संख्या मिल जाएगी। उदाहरण के लिए आपका यादृच्छिक जनरेटर 0.00001 और 0.00002 उत्पन्न कर सकता है लेकिन 0.000017 उत्पन्न नहीं कर सकता है। तो आपके पास एक समान वितरण है लेकिन कम परिशुद्धता (वास्तविक फ्लोटिंग पॉइंट की तुलना में 256 गुना कम परिशुद्धता) है।
डैनियलएचएचएच

10
@DanielHsH: ओपी ने विशेष रूप से पूछा कि यादृच्छिक झांकियों को उत्पन्न करने के लिए यांत्रिकी का क्या उपयोग किया जा सकता है rand()। यह सवाल, और मेरा जवाब, मूल रूप से मूल बातें सीखने पर केंद्रित था और सटीकता के उच्च डिग्री के बारे में चिंतित नहीं था। चलने से पहले आपको चलना सीखना होगा।
जॉन डिब्लिंग

137

C ++ 11 आपको कई नए विकल्प देता है random। इस विषय पर विहित कागज N3551, सी ++ 11 में रैंडम नंबर जनरेशन होगा

यह देखने के लिए कि rand()समस्याग्रस्त का उपयोग क्यों किया जा सकता है रैंड () गोइंगनेटिव 2013 ईवेंट के दौरान दिए गए स्टेपहान टी। लवविज द्वारा हानिकारक प्रस्तुति सामग्री पर विचार करें । स्लाइड्स टिप्पणियों में हैं, लेकिन यहां एक सीधा लिंक है

मैं इसका boostउपयोग करने के साथ-साथ randविरासत कोड को अभी भी इसके समर्थन की आवश्यकता कर सकता हूं ।

नीचे दिए गए उदाहरण को cppreference साइट से डिस्टिल्ड किया गया है और std :: mersenne_twister_engine इंजन और std का उपयोग करता है :: वर्दी_ real_distribution जो [0,10)अंतराल में नंबर उत्पन्न करता है, अन्य इंजनों के साथ और वितरित टिप्पणी करता है ( इसे लाइव देखें ):

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;

    //
    // Engines 
    //
    std::mt19937 e2(rd());
    //std::knuth_b e2(rd());
    //std::default_random_engine e2(rd()) ;

    //
    // Distribtuions
    //
    std::uniform_real_distribution<> dist(0, 10);
    //std::normal_distribution<> dist(2, 2);
    //std::student_t_distribution<> dist(5);
    //std::poisson_distribution<> dist(2);
    //std::extreme_value_distribution<> dist(0,2);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(e2))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

आउटपुट निम्न के समान होगा:

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

उत्पादन, इसलिए यदि हम साथ जाने का फैसला किया है जो वितरण आप चुनते हैं पर निर्भर करती है std :: normal_distribution के एक मूल्य के साथ 2दोनों के लिए मतलब और stddev जैसे dist(2, 2)बजाय उत्पादन इस के समान होगा ( यह सीधा प्रसारण दिखाई ):

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

निम्नलिखित प्रस्तुत कोड में से कुछ का संशोधित संस्करण है N3551( इसे लाइव देखें ):

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

std::default_random_engine & global_urng( )
{
    static std::default_random_engine u{};
    return u ;
}

void randomize( )
{
    static std::random_device rd{};
    global_urng().seed( rd() );
}

int main( )
{
  // Manufacture a deck of cards:
  using card = int;
  std::array<card,52> deck{};
  std::iota(deck.begin(), deck.end(), 0);

  randomize( ) ;  

  std::shuffle(deck.begin(), deck.end(), global_urng());
  // Display each card in the shuffled deck:
  auto suit = []( card c ) { return "SHDC"[c / 13]; };
  auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };

  for( card c : deck )
      std::cout << ' ' << rank(c) << suit(c);

   std::cout << std::endl;
}

परिणाम समान दिखेंगे:

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC केडी 9D 5C 4H 9C 8C 8C JC 5D 7C 7C 7S 8S TSC 2C 8D 3C 7 एस 6 एस

बढ़ावा

बेशक Boost.Random हमेशा एक विकल्प के रूप में अच्छी तरह से है, यहाँ मैं बढ़ावा का उपयोग कर रहा हूँ :: यादृच्छिक :: वर्दी_real_distribution :

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
    boost::random::mt19937 gen;
    boost::random::uniform_real_distribution<> dist(0, 10);

    std::map<int, int> hist;
    for (int n = 0; n < 10000; ++n) {
        ++hist[std::floor(dist(gen))];
    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

रैंड ()

यदि आप का उपयोग करना चाहिए rand()तो हम एक गाइड के लिए सी एफएक्यू पर जा सकते हैं मैं फ्लोटिंग-पॉइंट यादृच्छिक संख्या कैसे उत्पन्न कर सकता हूं? , जो मूल रूप से अंतराल पर उत्पन्न करने के लिए इसके समान एक उदाहरण देता है [0,1):

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

और इसमें से एक यादृच्छिक संख्या उत्पन्न करने के लिए [M,N):

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

1
क्या आप अपना randMToNpls ठीक कर सकते हैं ? या तो ध्यान दें कि यह ऊपर से है [M,N]या वापस जोड़ें । -> इसे इस तरह बुलाने के बारे में सोचें:+ 1.randZeroToOnerandMToN(0.0, 1.0);
BeyelerStudios

1
इसके अलावा शून्य पर विभाजन से सावधान रहें (N-M)। इस त्रुटि से निपटने का एक अच्छा तरीका यहां पाया गया है: stackoverflow.com/questions/33058848/…
डॉ। बनो

61

Boost.Random पर एक नज़र डालें । आप ऐसा कुछ कर सकते हैं:

float gen_random_float(float min, float max)
{
    boost::mt19937 rng;
    boost::uniform_real<float> u(min, max);
    boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
    return gen();
}

चारों ओर खेलें, आप हर बार एक नया निर्माण करने के बजाय उसी mt19937 ऑब्जेक्ट को बेहतर तरीके से पास कर सकते हैं, लेकिन उम्मीद है कि आपको यह विचार मिलेगा।


1
यूनिफ़ॉर्मल_अल्प-ओपन अंतराल [न्यूनतम, अधिकतम) का उपयोग करता है, जिसका अर्थ है कि आपको अपना न्यूनतम मूल्य मिलेगा लेकिन कभी भी अधिकतम मूल्य तक नहीं पहुंचेगा। यह विचार करने के लिए कुछ है, हालांकि यदि आप किसी तरह से गोल करते हैं, तो आप इस समस्या पर काबू पा सकते हैं।
तेहवन

20
यह अब C ++ 11 का हिस्सा है।
टॉमस आंद्रेल

व्यावहारिक अनुप्रयोगों में @ वुल्फ किसी भी विशिष्ट फ्लोटिंग पॉइंट वैल्यू को टकराने की संभावना इतनी कम है कि यह समापन बिंदु या शामिल किए जाने पर कोई फर्क नहीं पड़ता। यदि आपको जरूरत है maxलेकिन एक ओपन-एंड का उपयोग कर सकते हैं min, तो आप अंतराल को आसानी से उलट सकते हैं return min + max - gen();:।
मार्क रैनसम

26

आधुनिक में c++आप <random>हेडर का उपयोग कर सकते हैं जो साथ आया था c++11
यादृच्छिक प्राप्त करने के लिए floatआप उपयोग कर सकते हैं std::uniform_real_distribution<>

आप संख्याओं को उत्पन्न करने के लिए किसी फ़ंक्शन का उपयोग कर सकते हैं और यदि आप नहीं चाहते हैं कि संख्याएँ हर समय समान रहें, तो इंजन और वितरण सेट करें static
उदाहरण:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
    return dis(e);
}

यह floatकंटेनर में रखने के लिए आदर्श है जैसे std::vector:

int main()
{
    std::vector<float> nums;
    for (int i{}; i != 5; ++i) // Generate 5 random floats
        nums.emplace_back(get_random());

    for (const auto& i : nums) std::cout << i << " ";
}

उदाहरण आउटपुट:

0.0518757 0.969106 0.0985112 0.0895674 0.895542

std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1तकनीकी रूप से गलत है, 1.0 कभी उत्पन्न नहीं होगा, en.cppreference.com/w/cpp/numeric/random/… To create a distribution over the closed interval [a,b], std::nextafter(b, std::numeric_limits<RealType>::max()) may be used as the second parameter.
Troyseph

1
यह स्वीकृत उत्तर होना चाहिए, यह 2020 का है।
एलेक्स

25

कोड को दो floatमूल्यों के साथ कॉल करें, कोड किसी भी सीमा में काम करता है।

float rand_FloatRange(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}

यह उल्लेखनीय है कि यह C99 या C ++ 11 में fmaf()(या fma()C ++ में फ्लोट अधिभार के लिए ) एक संभावित उपयोग का मामला है , जो अधिक परिशुद्धता संरक्षित कर सकता है। के रूप में, में fmaf((float)rand() / RAND_MAX, b - a, a)
टिम Timस

22

यदि आप C ++ और C का उपयोग नहीं कर रहे हैं, तो याद रखें कि तकनीकी रिपोर्ट 1 (TR1) और C ++ 0x ड्राफ्ट में उन्होंने हेडर फ़ाइल में एक यादृच्छिक संख्या जनरेटर के लिए सुविधाएं जोड़ी हैं, मेरा मानना ​​है कि यह बूस्ट के समान है। सी लाइब्रेरी फ़ंक्शन की तुलना में रैंडम लाइब्रेरी और निश्चित रूप से अधिक लचीला और "आधुनिक", रैंड।

यह सिंटैक्स एक जनरेटर चुनने की क्षमता प्रदान करता है (जैसे मर्सिएन ट्विस्टर mt19937) और फिर एक वितरण (सामान्य, बरनौली, द्विपद आदि) का चयन करें।

सिंटेक्स इस प्रकार है ( इस साइट से उधार लिया गया बेशर्म ):

  #include <iostream>
  #include <random>

  ...

  std::tr1::mt19937 eng;  // a core engine class 
  std::tr1::normal_distribution<float> dist;     

  for (int i = 0; i < 10; ++i)        
      std::cout << dist(eng) << std::endl;

2
यह अब C ++ 11 में है, डिस्टेंस को मिनिमम और मैक्सिमम वैल्यू के साथ इनिशियलाइज़ किया जा सकता है।
.तिने

मुझे मिनिमल और मैक्सिमम को इनिशियलाइज़र में डालना और वैल्यू मिलने पर जनरेटर प्रदान करना मुझे अजीब लगता है - मैं पसंद करूंगा कि क्या यह अन्य तरीके से होता है, ओह वेल।
योयो

6

कुछ प्रणालियों पर (वर्तमान में, वीसी स्प्रिंग्स के साथ विंडोज दिमाग में), RAND_MAXहास्यास्पद रूप से छोटा है, i। इ। केवल 15 बिट। जब RAND_MAXआपके द्वारा विभाजित किया जाता है तो केवल 23 संभव बिट्स के बजाय 15 बिट का एक मंटिसा उत्पन्न कर रहा है। यह आपके लिए एक समस्या हो सकती है या नहीं भी हो सकती है, लेकिन आप उस मामले में कुछ मूल्यों को याद कर रहे हैं।

ओह, बस ध्यान दिया कि उस समस्या के लिए पहले से ही एक टिप्पणी थी। वैसे भी, यहाँ कुछ कोड है जो आपके लिए इसे हल कर सकते हैं:

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

अप्रमाणित, लेकिन काम कर सकते हैं :-)


क्या फ़्लोट आर = (फ्लोट) ((रैंड () << 9) | रैंड ()) / RAND_MAX के बारे में? (यह भी पता नहीं)
ट्रैप

क्षमा करें, क्षमा करें, RAND_MAX द्वारा विभाजित करना आपको कहीं भी नहीं ले जाएगा ... इस ट्रिक के पूरे बिंदु के लिए कुछ ऐसा था जो RAND_MAX से बड़ा हो ... तय किया कि मेरे लिए भी।
जोए

2
सिद्धांत के बिना यादृच्छिक संख्याओं की रचना के बारे में सावधान रहें ... रैंड () को लगातार कॉल करना पूरी तरह से स्वतंत्र नहीं हो सकता है। संकेत: यदि इसका एक रैखिक अभिनंदन जनरेटर, लगातार कॉल पर कम बिट देखता है: यह 0 और 1. के बीच वैकल्पिक होता है
RBerteig

मुझे पता है। कुछ अनुप्रयोगों के लिए यह पर्याप्त हो सकता है, हालांकि। लेकिन हां, आपको शायद इस मामले में केवल दो कॉल से अधिक का उपयोग करना चाहिए। इस मामले में कोई चांदी की गोली नहीं है, आप इसे LCG होने पर भी भरोसा नहीं कर सकते। अन्य PRNG में कमजोर बिट्स होते हैं। बूस्ट समाधान यहां सबसे अच्छा होना चाहिए।
जोए

(nb: MSVC में रैंड द्वारा लौटाया गया कम बिट RNG स्टेट का सबसे कम बिट नहीं है। 100 रैंड () कॉल के लिए मुझे निम्नलिखित मिलते हैं: 1100100000111111101010010010001010101111101011111001100110000000001010110010010010010010001010110010001011.81 48-LC में LC का उपयोग करता है। इसी तरह करना)
जॉय

4

drand48(3)POSIX मानक तरीका है। GLibC भी एक रीएंटेंट संस्करण प्रदान करता है drand48_r(3),।

समारोह SVID 3 में अप्रचलित घोषित किया गया था लेकिन कोई पर्याप्त विकल्प प्रदान नहीं किया गया था इसलिए IEEE Std 1003.1-2013 में अभी भी इसे शामिल किया गया है और इसमें कोई भी नोट नहीं है कि यह जल्द ही कहीं भी जा रहा है।

विंडोज में, मानक तरीका CryptGenRandom () है


2

मैं अब तक किसी भी उत्तर से संतुष्ट नहीं था, इसलिए मैंने एक नया यादृच्छिक फ्लोट फ़ंक्शन लिखा। यह फ्लोट डेटा प्रकार के बारे में बिटवाइज़ धारणा बनाता है। इसे अभी भी कम से कम 15 यादृच्छिक बिट्स के साथ एक रैंड () फ़ंक्शन की आवश्यकता है।

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}

7
दिलचस्प दृष्टिकोण, मैं वोट दें करना चाहते हैं लेकिन, मैं सच में समझ में नहीं आता क्या हो रहा है
hasen

2

मेरी राय में उपरोक्त उत्तर कुछ 'यादृच्छिक' फ्लोट देते हैं, लेकिन उनमें से कोई भी वास्तव में एक यादृच्छिक फ्लोट नहीं है (यानी वे फ्लोट प्रतिनिधित्व का एक हिस्सा याद करते हैं)। इससे पहले कि मैं अपने कार्यान्वयन में भाग लूंगा पहले तैरने के लिए ANSI / IEEE मानक प्रारूप पर एक नज़र डालते हैं:

| संकेत (1-बिट) | e (8-बिट्स) | f (23-बिट) |

इस शब्द द्वारा दर्शाई गई संख्या है (-1 * साइन) * 2 ^ ई * 1. एफ

ध्यान दें कि 'ई' संख्या एक पक्षपाती है (127 के पूर्वाग्रह के साथ) संख्या -127 से 126 तक है। सबसे सरल (और वास्तव में सबसे यादृच्छिक) फ़ंक्शन सिर्फ एक फ्लोट में एक यादृच्छिक इंट के डेटा को लिखना है, इस प्रकार

int tmp = rand();
float f = (float)*((float*)&tmp);

ध्यान दें कि यदि आप ऐसा करते हैं तो float f = (float)rand();यह पूर्णांक को एक फ्लोट में बदल देगा (इस प्रकार 10 10.0 हो जाएगा)।

तो अब अगर आप अधिकतम मूल्य को सीमित करना चाहते हैं, तो आप कुछ कर सकते हैं जैसे (सुनिश्चित नहीं है कि यह काम करता है)

int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f       // note float to int conversion!
tmp %= max_number;
f -= tmp;

लेकिन यदि आप फ्लोट की संरचना को देखते हैं, तो आप देख सकते हैं कि एक फ्लोट का अधिकतम मूल्य (लगभग) 2 ^ 127 है जो एक इंट (2 ^ 32) के अधिकतम मूल्य के रूप में बड़ा है, इस प्रकार एक महत्वपूर्ण भाग को खारिज कर रहा है संख्या जो एक फ्लोट द्वारा दर्शाई जा सकती है। यह मेरा अंतिम कार्यान्वयन है:

/**
 * Function generates a random float using the upper_bound float to determine 
 * the upper bound for the exponent and for the fractional part.
 * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
 * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
 * @param sign_flag if sign_flag = 0 the random number is always positive, if 
 *              sign_flag = 1 then the sign bit is random as well
 * @return a random float
 */
float randf(int min_exp, int max_exp, char sign_flag) {
    assert(min_exp <= max_exp);

    int min_exp_mod = min_exp + 126;

    int sign_mod = sign_flag + 1;
    int frac_mod = (1 << 23);

    int s = rand() % sign_mod;  // note x % 1 = 0
    int e = (rand() % max_exp) + min_exp_mod;
    int f = rand() % frac_mod;

    int tmp = (s << 31) | (e << 23) | f;

    float r = (float)*((float*)(&tmp));

    /** uncomment if you want to see the structure of the float. */
//    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);

    return r;
}

इस फ़ंक्शन का उपयोग करके randf(0, 8, 0)0.0 और 255.0 के बीच एक यादृच्छिक संख्या वापस आ जाएगी


1
आपकी गलती है। रैंड ()% frac_mod काम नहीं करेगा क्योंकि MAX_RAND आमतौर पर (1 << 23) से कम है।
डैनियल एचएचएच

मुझे यह स्वीकार करना होगा कि मुझे MAX_RAND का सटीक आकार नहीं पता है। कभी भी कम नहीं यह अभी भी काम करेगा, शायद यह एक बेकार बयान है, लेकिन यह अभी भी काम करेगा। 8% 10 = 8 तो ठीक है, लेकिन अगर MAX_RAND हमेशा छोटा है तो (1 << 23) आप वास्तव में इसे हटा सकते हैं।
user2546926

2
नहीं, आप थोड़े गलत हैं। RandMax आमतौर पर ~ 65,000 है। इसका मतलब है कि 23 बिट्स से आप केवल 15 यादृच्छिक बनाते हैं। दूसरे शायद शून्य होंगे। आप वास्तव में यादृच्छिक संख्या कम परिशुद्धता के मिल जाएगा। उदाहरण के लिए आपका यादृच्छिक जनरेटर 0.001 और 0.002 उत्पन्न कर सकता है लेकिन 0.0017 उत्पन्न नहीं कर सकता है। तो आपके पास एक समान वितरण है लेकिन कम परिशुद्धता (फ्लोट की तुलना में 256 गुना कम परिशुद्धता) है।
डैनियलएचएचएस

इस उत्तर में दो गलतियाँ हैं। घातांक सीमा तय करना: int e = (rand() % (max_exp - min_exp)) + min_exp_mod;और मंटिसा: int f = (int)(frac_mod * (float)rand() / RAND_MAX);ऊपर अपनी संबंधित पंक्तियों को बदलना। ध्यान दें कि मंटिसा गलती प्रमुख है: RAND_MAXछोटे के लिए 1 << 23आप केवल कम महत्वपूर्ण बिट्स को यादृच्छिक करेंगे और हर समय सबसे महत्वपूर्ण बिट्स के लिए 0s प्राप्त करें!
बेयेलरस्टूडिओस

2

यदि आप जानते हैं कि आपका फ्लोटिंग पॉइंट फॉर्मेट IEEE 754 (इंटेल और एआरएम सहित लगभग सभी आधुनिक सीपीयू) है, तो आप बिट-वार तरीकों का उपयोग करके रैंडम पूर्णांक से रैंडम फ्लोटिंग पॉइंट नंबर बना सकते हैं। यह केवल तभी माना जाना चाहिए जब आपके पास C ++ 11 की पहुंच न हो randomया Boost.Randomजो दोनों बहुत बेहतर हों।

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

यह विभाजन का उपयोग करके एक से बेहतर वितरण देगा।


8
मुझे यकीन नहीं है कि आप क्यों कह रहे हैं कि यह "बेहतर वितरण" देगा। वास्तव में, यह बिल्कुल उसी तरह का वितरण देगा जैसा कि अभी भी है return (float)random23 / (1 << 23)। (हां, मैंने अभी-अभी इसका परीक्षण किया है , आपके फ़ंक्शन को random32एक पैरामीटर के रूप में लेने के लिए और इसे शून्य से लेकर सभी मानों तक चलाने के लिए संशोधित किया है (1 << 23)-1। और हां, आपकी विधि वास्तव में विभाजन के समान परिणाम देती है 1 << 23।)
इल्मरी करोनें

1

C ++ के लिए, यह distचर द्वारा निर्दिष्ट सीमा के भीतर वास्तविक फ्लोट नंबर उत्पन्न कर सकता है

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}

1
क्या आपने केवल इस उत्तर से कोड कॉपी और पेस्ट किया था? stackoverflow.com/a/1118739/1538531
डेरेक

वास्तव में नहीं। मुझे यह देखकर थोड़ा आश्चर्य हुआ कि वे एक जैसे दिखते हैं! लेकिन मैंने इंजन-जनरेटर जनवरी 1,1970 को इनिशियलाइज़ किया।
मार्को 167

काफी उचित। मैंने नोटिस किया कि आपने जेनरेटर को युगांतर के लिए इनिशियलाइज़ किया है, लेकिन उस कोड के समान है!
डेरेक

मुझे TR1 का उदाहरण देना थोड़ा अजीब लगता है, क्या आप बता सकते हैं कि C ++ 11 के विपरीत किसी को किन मामलों में TR1 का उपयोग करना होगा?
शाफिक याघमोर

0

रैंड () 0 और RAND_MAX के बीच एक इंट वापस करें। 0.0 और 1.0 के बीच एक यादृच्छिक संख्या प्राप्त करने के लिए, पहले एक फ्लोट के लिए रैंड () द्वारा इंटर्न रिटर्न डालें, फिर RAND_MAX द्वारा विभाजित करें।


0
#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

मैं दो उत्तर नहीं दे सका, इसलिए यहां दूसरा समाधान है। log2 यादृच्छिक संख्या, 0.0f की ओर बड़े पैमाने पर पूर्वाग्रह लेकिन यह वास्तव में एक यादृच्छिक नाव 1.0f से 0.0f है।

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.