Rastgele kayan sayı oluşturma


271

C ++ 'da rasgele değişkenler nasıl oluştururum?

Tamsayı rand'ı alıp bir şeye bölebileceğimi düşündüm, bu yeterli mi?


2
Bu, sayının ne istediğinize ve ne kadar rasgele olduğuna bağlıdır. genellikle rand () 15 bit rasgelelik verir, ancak şamandıralar 23 bit hassasiyete sahiptir, bu nedenle bazı değerleri kaçırır.
Pete Kirkham

1
Cevabımı mevcut tüm önemli seçenekleri içerecek şekilde güncelledim ve randomC ++ 11'de eklenen başlığa odaklanma seçimim , C ++ 14'teki standart N3924: Cesaret kırıcı rand () belgesi ile destekleniyor . Ben dahil rand()çoğunlukla tarihsel değerlendirmeler için cevabım aynı zamanda eski uygulama mevcut olamayacağı fark.
Shafik Yaghmour

Cevabım, <random>başlık ile her seferinde aynı sayıların alınmasını nasıl önleyeceğini içerir
Andreas DM

Yanıtlar:


381

rand()C ++ 'da sahte rasgele sayılar üretmek için kullanılabilir. İle birlikte RAND_MAXve biraz matematik, dilediğiniz keyfi aralıkta rastgele sayılar üretebilirsiniz. Bu, öğrenme amaçları ve oyuncak programları için yeterlidir. Normal dağılıma sahip gerçekten rastgele sayılara ihtiyacınız varsa , daha gelişmiş bir yöntem kullanmanız gerekir.


Bu, 0.0 ile 1.0 arasında bir sayı üretecektir.

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

Bu keyfi bir 0.0 arasında bir sayı oluşturur float, X:

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

Bu, bazı keyfi LOveya bazı keyfi bir sayı oluşturur HI:

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

Not rand()Eğer gerçekten rasgele sayılar gerekirse fonksiyon genellikle yeterli olmayacaktır.


Aramadan önce, arayarak rand()rasgele sayı üretecini "tohumlamanız" gerekir srand(). Bu, programın çalışması sırasında bir kez yapılmalıdır - her aradığınızda değil rand(). Bu genellikle şu şekilde yapılır:

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

Aramak için randya da srandgerekir #include <cstdlib>.

Aramak için timeyapmanız gerekir #include <ctime>.


22
İlk önce tohumlamayı unutmayın!
Klaim

14
Her iki sınırın da kapsayıcı olduğunu unutmayın.
dmckee --- eski moderatör yavru kedi

14
Bu cevap yanıltıcı. Geçen hafta Going Native 2013'te ele alındı; rand () Zararlı olarak kabul edilir, çok ayrıntılı bir açıklama için channel9.msdn.com/Events/GoingNative/2013/… .
Ade Miller

14
Bu kadar çok insanın neden bu cevabı iptal ettiğini anlamıyorum. Matematiksel olarak yanlış. RAND_MAX çok küçük bir sayıdır (genellikle 2 ^ 16). Bu, kayan noktanın 23 bitinden sadece 15 rastgele yaptığınız anlamına gelir. Diğerleri muhtemelen sıfır olacaktır. Gerçekten tekdüze dağılımda rastgele sayılar elde edersiniz, ancak düşük doğruluktadır. Örneğin rastgele üreteciniz 0.00001 ve 0.00002 üretebilir, ancak 0.000017 üretemez. Böylece tekdüze bir dağılımınız var ancak düşük hassasiyetli (gerçek kayan noktadan 256 kat daha az hassasiyet).
DanielHsH

10
@DanielHsH: OP özellikle rastgele şamandıralar oluşturmak için hangi mekaniğin kullanılabileceğini sordu rand(). Bu soru ve benim cevabım, özellikle temelleri öğrenmeye odaklanmıştı ve yüksek derecede hassasiyetle ilgili değildi. Koşmayı öğrenmeden önce yürümeyi öğrenmelisin.
John Dibling

137

C ++ 11 size birçok yeni seçenek sunar random. Bu konudaki kanonik yazı C35'te N3551, Rastgele Sayı Üretimi olacaktır.

Neden kullandığınızı görmek için rand() sorunlu olabileceğini görmek için GoingNative 2013 etkinliği sırasında verilen Stephan T. Lavavej tarafından hazırlanan Zararlı sunum materyali dikkate alın . Slaytlar yorumlarda yer alıyor, ancak burada doğrudan bir bağlantı var .

Ayrıca boost, randeski kod hala desteğini gerektirebileceği için de kullanıyorum .

Aşağıdaki örnek cppreference sitesinden damıtılmıştır ve std :: mersenne_twister_engine engine ve std :: uniform_real_distribution sayıları üretir [0,10)dışarı yorumladı diğer motorlar ve dağılımları aralık, ( o canlı izlemek ):

#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';
    }
}

çıktı aşağıdakine benzer olacaktır:

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

Çıktı, hangi dağıtımı seçtiğinize bağlı olarak değişecektir, bu nedenle std :: normal_distribution ile 2her ikisini de içeren bir değerle gitmeye karar verirsek ortalama ve STDDEVP örn dist(2, 2)yerine çıkış buna benzer olacağını ( o canlı izlemek ):

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

Aşağıda sunulan kodun bazılarının değiştirilmiş bir sürümüdür N3551( canlı olarak görün ):

#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;
}

Sonuçlar şuna benzer:

5S 5S 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 KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

artırmak

Tabii Boost.Random da her zaman bir seçenek, burada kullanıyorum boost :: random :: uniform_real_distribution kullanıyorum :

#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 ()

Kullanmanız gerekiyorsa , kayan noktalı rasgele sayılar nasıl oluşturabilirim konusunda bir kılavuz için C SSS bölümünerand() gidebiliriz., temelde aralıkta bir açık oluşturmak için buna benzer bir örnek verir.[0,1) :

#include <stdlib.h>

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

ve aralığından rastgele bir sayı oluşturmak için [M,N):

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

1
randMToNpls düzeltmek ? ya not edin [M,N]ya + 1.da yukarıdan ekleyin randZeroToOne. -> böyle çağırmayı düşünün:randMToN(0.0, 1.0);
BeyelerStudios

1
Ayrıca sıfıra bölme konusunda da dikkatli olun (N-M). Bu hatayla başa çıkmanın güzel bir yolu burada bulunabilir: stackoverflow.com/questions/33058848/…
Dr Beco

61

Boost.Random'a bir göz atın . Böyle bir şey yapabilirsiniz:

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();
}

Oyun oynayın, her seferinde yeni bir tane oluşturmak yerine aynı mt19937 nesnesini geçmek daha iyi olabilir, ancak umarım fikir alırsınız.


1
uniform_real yarı açık bir aralık [dak, maks.) kullanır, bu da minimum değerinizi elde edeceğiniz ancak asla maksimum değere ulaşamayacağınız anlamına gelir. Dikkate alınması gereken bir şey, ancak bir şekilde yuvarlarsanız, bu sorunu aşabilirsiniz.
TehWan

20
Bu artık C ++ 11'in bir parçası.
Tomas Andrle

Pratik uygulamalarda herhangi bir kayan nokta değerine çarpma olasılığı o kadar düşüktür ki uç noktanın dahil edilmesi veya hariç tutulması önemli değildir. Eğer gerekiyorsa maxancak açık uçlu kullanabilirsiniz min, kolayca aralığını tersine çevirebilirsiniz: return min + max - gen();.
Mark Ransom

26

Modern olarak c++kullanmak olabilir <random>birlikte gelen başlığı c++11.
Rastgele almak floatiçin kullanabilirsiniz std::uniform_real_distribution<>.

Sayıları oluşturmak için bir işlev kullanabilirsiniz ve sayıların her zaman aynı olmasını istemiyorsanız motoru ve dağıtımı ayarlayın static.
Misal:

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

float'Leri aşağıdaki gibi bir kaba yerleştirmek idealdir 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 << " ";
}

Örnek çıktı:

0.0518757 0.969106 0.0985112 0.0895674 0.895542

std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1teknik olarak yanlıştır, 1.0 asla üretilmeyecektir, bkz. 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
Bu kabul edilen cevap olmalı, 2020'yi korkutuyor.
Alex

25

Kodu iki floatdeğerle çağırın, kod herhangi bir aralıkta çalışır.

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

Bunun , C99 veya C ++ 11'deki (veya C ++ 'da fmaf()şamandıra fma()aşırı yükü) için daha fazla hassasiyet koruyabilecek potansiyel bir kullanım durumu olduğunu belirtmek gerekebilir. Olduğu gibi fmaf((float)rand() / RAND_MAX, b - a, a),.
Tim Čas

22

C ++ değil C ++ kullanıyorsanız, teknik rapor 1'de (TR1) ve C ++ 0x taslağında, başlık dosyasında rasgele sayı üreteci için olanaklar eklediklerini, bunun Boost ile aynı olduğuna inanıyorum. Rastgele kütüphane ve kesinlikle C kütüphane fonksiyonundan daha esnek ve "modern" rand.

Bu sözdizimi bir jeneratör seçme yeteneği sunar ( mersenne twister gibi mt19937 gibi) ve ardından bir dağıtım (normal, bernoulli, binomial vb.) .

Sözdizimi aşağıdaki gibidir ( bu siteden utanmaz bir şekilde ödünç alınmıştır ):

  #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
Bu şimdi C ++ 11'de, ayrıca dist bir min ve max değerleri ile başlatılabilir.
Étienne

Min ve max başlatıcı koymak ve bir değer alırken jeneratör sağlamak bana garip görünüyor - başka türlü olsaydı tercih ederim, oh iyi.
yoyo

6

Bazı sistemlerde (şu anda akılda VC yayları olan Windows) RAND_MAXgülünç derecede küçük, i. e. sadece 15 bit. İle bölündüğündeRAND_MAX sadece 15 mantisi ürettiğini yerine 23 olası bit bit. Bu sizin için bir sorun olabilir veya olmayabilir, ancak bu durumda bazı değerleri kaçırıyorsunuz.

Oh, bu problem için zaten bir yorum olduğunu fark ettim. Her neyse, işte bunu sizin için çözebilecek bazı kodlar:

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

Test edilmedi, ancak işe yarayabilir :-)


Float r = (float) ((rand () << 9) | rand ()) / RAND_MAX hakkında ne dersiniz? (ayrıca test edilmedi)
Tuzak

Ah, üzgünüm, RAND_MAX'a bölmek seni hiçbir yere götürmeyecek ... Bu hilenin asıl amacı RAND_MAX'tan daha büyük bir şeye sahip olmaktı ... bunu benim için de düzeltti.
Joey

2
Teori olmadan rastgele sayılar oluşturma konusunda dikkatli olun ... arka arkaya rand () çağrıları tamamen bağımsız olmayabilir. İpucu: eğer doğrusal bir uyumlu jeneratör ise, ardışık aramalarda düşük biti izleyin: 0 ile 1 arasında
değişir

Biliyorum. Bazı uygulamalar için bu yeterli olabilir. Ama evet, muhtemelen bu durumda sadece ikiden fazla çağrı kullanmalısınız. Bu durumda gümüş mermi yok, bir LCG olmasına bile güvenemezsiniz. Diğer PRNG'ler zayıf yüksek bitlere sahiptir. Boost çözümü burada en iyisi olmalıdır.
Joey

(nb: rand tarafından MSVC'de döndürülen düşük bit, RNG durumunun en düşük biti değildir. 100 rand () çağrısı için aşağıdakileri alıyorum: 1100100000111111101010010011010101110110110111010011111100100000000010100011011000000100101100011. Java 48 bit LCG kullanıyor ve sadece 32 bit kullanıyor benzer şekilde yapmak için)
Joey


2

Şimdiye kadar cevapların hiçbirinden memnun kalmadım, bu yüzden yeni bir rastgele şamandıra fonksiyonu yazdım. Kayan noktalı veri türü hakkında bitsel varsayımlar yapar. Yine de en az 15 rastgele bit içeren bir rand () işlevine ihtiyacı vardır.

//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
ilginç bir yaklaşım, ben upvote istiyorum ama, gerçekten ne olduğunu anlamıyorum
hasen

2

Bence yukarıdaki cevap bazı 'rastgele' şamandıra veriyor, ancak bunların hiçbiri gerçekten rastgele bir şamandıra değil (yani şamandıra temsilinin bir kısmını kaçırıyorlar). Benim uygulama acele önce önce yüzen için ANSI / IEEE standart biçimine bir göz atalım:

| işareti (1 bit) | e (8 bit) | f (23 bit) |

bu kelimenin temsil ettiği sayı (-1 * işareti) * 2 ^ e * 1.f

'e' numarasının -127 ile 126 arasında değişen bir yanlı (127 önyargı ile) sayı olduğuna dikkat edin. En basit (ve aslında en rastgele) fonksiyon rastgele bir int'in verilerini bir şamandıra içine yazmaktır, Böylece

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

eğer bunu yaparsanız float f = (float)rand();tamsayıyı bir kayan noktaya dönüştürür (böylece 10 10.0 olur).

Şimdi maksimum değeri sınırlamak istiyorsanız, böyle bir şey yapabilirsiniz (bunun işe yarayıp yaramadığından emin değilsiniz)

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

ancak şamandıranın yapısına bakarsanız, bir şamandıranın maksimum değerinin (yaklaşık) 2 ^ 127 olduğunu görebilirsiniz. bir kayan nokta ile temsil edilebilecek sayılar. Bu benim son uygulamam:

/**
 * 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;
}

bu işlevi kullanmak randf(0, 8, 0)0,0 ile 255,0 arasında rastgele bir sayı döndürür


1
senin bir hatan var. rand ()% frac_mod, MAX_RAND genellikle (1 << 23) değerinden daha düşük olduğu için çalışmaz.
DanielHsH

MAX_RAND'ın tam boyutunu bilmediğimi itiraf etmeliyim. Asla daha az işe yaramayacak, belki işe yaramaz bir ifade, ama yine de işe yarayacak. 8% 10 = 8 bu kadar iyi, ama MAX_RAND her zaman daha küçükse (1 << 23) gerçekten kaldırabilirsiniz.
user2546926

2
Hayır, biraz yanılıyorsun. RandMax tipik olarak ~ 65.000'dir. Bu, 23 bitten sadece 15 rastgele yaptığınız anlamına gelir. Diğerleri muhtemelen sıfır olacaktır. Gerçekten rastgele sayılar elde edersiniz, ancak düşük hassasiyete sahiptir. Örneğin, rastgele üreteciniz 0.001 ve 0.002 üretebilir, ancak 0.0017 üretemez. Böylece tekdüze bir dağılımınız var ancak düşük hassasiyetli (şamandıradan 256 kat daha az hassasiyet).
DanielHsH

Bu cevapta iki hata var. Üs aralığı: int e = (rand() % (max_exp - min_exp)) + min_exp_mod;ve mantis: int f = (int)(frac_mod * (float)rand() / RAND_MAX);yukarıdaki ilgili satırlarını değiştirerek. Mantis yanılgısının büyük olduğuna dikkat edin: RAND_MAXdaha 1 << 23küçükler için sadece daha düşük anlamlı bitleri rasgele seçer ve her zaman en önemli bitler için 0 alırsınız!
BeyelerStudios

2

Kayan nokta biçiminizin IEEE 754 (Intel ve ARM dahil olmak üzere neredeyse tüm modern CPU'lar) olduğunu biliyorsanız, bit bilge yöntemleri kullanarak rastgele bir tam sayıdan rastgele bir kayan nokta sayısı oluşturabilirsiniz. Bu, yalnızca C ++ 11'lere erişiminiz yoksa randomveya Boost.Randomher ikisi de çok daha iyi ise dikkate alınmalıdır .

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;
}

Bu, bölümü kullanandan daha iyi bir dağıtım sağlayacaktır.


8
Bunun neden "daha iyi bir dağıtım" sağlayacağını söylediğinizden emin değilim. Aslında, bu tam olarak aynı dağılımı verecektir return (float)random23 / (1 << 23). (Evet, bunu test ettim , işlevinizi random32bir parametre olarak alacak şekilde değiştirdim ve sıfırdan sonuna kadar tüm değerler için çalıştırıyorum (1 << 23)-1. Ve evet, yönteminiz gerçekten de bölme ile aynı sonuçları veriyor 1 << 23.)
Ilmari Karonen

1

C ++ için, distdeğişken tarafından belirtilen aralıkta gerçek kayan sayı üretebilir

#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
Bu cevaptaki kodu kopyalayıp yapıştırdınız mı? stackoverflow.com/a/1118739/1538531
Derek

Aslında hayır. Ne kadar benzediklerini görünce biraz şaşırdım! Ama motor jeneratörünü 1,1970 Ocak başlattım.
Marco167

Yeterince adil. Jeneratörü çağa başlattığınızı fark ettim, ama bu kodun benzer olduğunu lanetleyin!
Derek

TR1 örneği vermek biraz garip geliyor, hangi durumlarda birisinin C ++ 11 yerine TR1 kullanması gerektiğini açıklayabilir misiniz?
Shafik Yaghmour

0

rand (), 0 ile RAND_MAX arasında bir int döndürür. 0.0 ile 1.0 arasında rastgele bir sayı elde etmek için önce int dönüşünü rand () ile bir kayan noktaya yayınlayın, sonra RAND_MAX ile bölün.


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));
...

İki cevap gönderemedim, işte ikinci çözüm. log2 rasgele sayılar, 0.0f'ye doğru büyük yanlılık ama gerçekten 1.0f ila 0.0f arasında rastgele bir şamandıra.

#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));
...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.