Tüm aralıkta eşit olarak rastgele sayılar oluşturun


94

Belirli bir aralıkta [maks; min] rastgele sayılar üretmem gerekiyor.

Ayrıca, rastgele sayılar belirli bir noktaya yerleştirilmemeli, aralık boyunca eşit olarak dağıtılmalıdır.

Şu anda şu şekilde oluşturuyorum:

for(int i=0; i<6; i++)
{
    DWORD random = rand()%(max-min+1) + min;
}

Testlerimden rastgele sayılar yalnızca bir nokta etrafında üretiliyor.

Example
min = 3604607;
max = 7654607;

Oluşturulan rastgele sayılar:

3631594
3609293
3630000
3628441
3636376
3621404

Aşağıdaki cevaplardan: Tamam, RAND_MAX 32767'dir. C ++ Windows platformundayım. Düzgün dağılımla rastgele sayılar üretmenin başka bir yöntemi var mı?


2
Bir Zar-O-Matic Oluşturun
Jarett Millard

1
C ++ 'ların rand()tek tip olduğu hakkında hiçbir fikrim yoktu . Hangi kütüphaneyi kullanıyorsunuz? cstdlib.h'ler rand(): tekdüze değildir cplusplus.com/reference/cstdlib/rand
Mike Warren

3
Hayır, rand () tek tiptir (bazı eski hatalı uygulamalar hariç). tekdüze olmayan şey, aralığı sınırlamak için modül '%' operatörünü kullanmaktır. Uygun bir çözüm için stackoverflow.com/questions/2999075/… adresine bakın veya 'arc4random_uniform' varsa, bunu doğrudan da kullanabilirsiniz.
John Meacham

@ Alien01: Kabul edilen yanıtı "Ayakkabı" ile değiştirmeyi düşünür müsünüz ("Rand neden kötü bir fikirdir" vb.)? Cevabım gerçekten güncel değil ve bunun için her olumlu oy aldığımda birinin yanlış koridorda koştuğunu hissediyorum.
peterchen

C ++ 11'de rastgele hakkında güzel teknik inceleme .
Pupsik

Yanıtlar:


157

Neden randkötü bir fikir

Burada aldığınız yanıtların çoğu, randfonksiyon ve modül operatöründen yararlanıyor. Bu yöntem , sayıları tek tip olarak üretmeyebilir (aralığına ve değerine bağlıdır RAND_MAX) ve bu nedenle önerilmez.

C ++ 11 ve bir aralıkta nesil

C ++ 11 ile birden çok başka seçenek yükseldi. Biri oldukça güzel bir aralıkta rastgele bir sayı üretmek için, gereksinimlerinizi: std::uniform_int_distribution. İşte bir örnek:

const int range_from  = 0;
const int range_to    = 10;
std::random_device                  rand_dev;
std::mt19937                        generator(rand_dev());
std::uniform_int_distribution<int>  distr(range_from, range_to);

std::cout << distr(generator) << '\n';

Ve işte çalışan örnek.

Diğer rastgele üreteçler

<random>Başlık Bernoulli, Poisson ve normal olmak üzere dağılımları farklı tür sayısız diğer rasgele sayı jeneratörler sunmaktadır.

Bir konteyneri nasıl karıştırabilirim?

Standart std::shuffleaşağıdakileri sağlar:

std::vector<int> vec = {4, 8, 15, 16, 23, 42};

std::random_device random_dev;
std::mt19937       generator(random_dev());

std::shuffle(vec.begin(), vec.end(), generator);

Algoritma, elementleri doğrusal bir karmaşıklıkla rastgele yeniden sıralayacaktır.

Boost.Random

C ++ 11 + derleyicisine erişiminiz yoksa başka bir alternatif, Boost.Random kullanmaktır . Arayüzü C ++ 11'e çok benzer.


24
Çok daha modern olduğu için bu yanıta DİKKAT EDİN.
gsamaras

Bu doğru cevap. Teşekkürler! Yine de, bu kodun her adımının daha derinlemesine bir açıklamasını görmek istiyorum. Örneğin, mt19937tür nedir?
Apollo

@Apollo Belgelerde "32-bit Mersenne Twister, Matsumoto ve Nishimura, 1998" yazıyor. Sözde rastgele sayılar üretmek için bir algoritma olduğunu varsayıyorum.
Shoe

@Shoe, belirli bir aralık için, aynı sırayla sayılar üretir 1 9 6 2 8 7 1 4 7 7. Programı her çalıştırdığımızda bunu nasıl rastgele hale getirebilirsiniz?

1
@Richard Alternatif nedir?
Shoe

60

[değiştir] Uyarı: rand()İstatistikler, simülasyon, kriptografi veya ciddi herhangi bir şey için kullanmayın .

Acelesi olan tipik bir insan için sayıların rastgele görünmesini sağlamak yeterince iyidir , artık değil.

Daha iyi seçenekler için @ Jefffrey'in cevabına veya kripto güvenli rasgele sayılar için bu cevaba bakın.


Genellikle, yüksek bitler, düşük bitlerden daha iyi bir dağılım gösterir, bu nedenle basit amaçlar için bir aralığın rastgele sayılarını oluşturmanın önerilen yolu şudur:

((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

Not : RAND_MAX + 1'in taşmamasına dikkat edin (teşekkürler Demi)!

Bölme [0, 1) aralığında rastgele bir sayı üretir; bunu gerekli aralığa "uzatın". Yalnızca max-min + 1, RAND_MAX'a yaklaştığında, Mark Ransom tarafından yayınlanan bir "BigRand ()" işlevine ihtiyacınız vardır.

Bu aynı zamanda, sayılarınızı daha da kötüleştirebilecek modulo nedeniyle bazı dilimleme sorunlarını da önler.


Yerleşik rastgele sayı oluşturucunun istatistiksel simülasyonlar için gerekli kaliteye sahip olduğu garanti edilmez. Sayıların bir insana "rastgele görünmesi" sorun değil, ancak ciddi bir uygulama için daha iyi bir şey almalısınız - veya en azından özelliklerini kontrol etmelisiniz (düzgün dağılım genellikle iyidir, ancak değerler korelasyon eğilimindedir ve dizi deterministiktir ). Knuth'un rastgele sayı üreteçleri üzerine (okunması zor olsa da) mükemmel bir incelemesi var ve son zamanlarda LFSR'nin mükemmel olduğunu ve özellikleri sizin için uygun olduğu için uygulanması çok basit olduğunu gördüm .


4
BigRand, istenen aralık RAND_MAX'ı geçmese bile daha iyi sonuçlar verebilir. RAND_MAX'ın 32767 olduğunu ve 32767 olası değeri istediğinizi düşünün - bu 32768 rastgele sayıdan ikisi (sıfır dahil) aynı çıktıya eşlenecek ve oluşma olasılığı diğerlerinden iki kat daha fazla olacaktır. Neredeyse ideal bir rastgele özellik!
Mark Ransom

8
(RAND_MAX + 1) kötü bir fikir. Bu, devredilebilir ve size negatif bir değer verebilir. Şunun gibi bir şey yapmak daha iyidir: ((çift) RAND_MAX) + 1.0
Demi

4
@peterchen: Sanırım demi'nin ne dediğini yanlış anladınız. Bunu kastetti: ( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min Dönüşümü ikiye katlayın ve sorunu önleyin.
Ördek mölemeye

3
Ayrıca, bu, yalnızca aralıktaki en alt 32767 değerden, aralıktaki eşit olarak dağıtılmış 32767 değere dağılımı değiştirir ve kalan 4017233 değerleri asla bu algoritma tarafından seçilmez.
Ördek mölemeye

2
Verilen cevap 1 puan kapalı. Doğru denklem: ((double) rand () / (RAND_MAX + 1.0)) * (max-min) + min "max-min + 1",% not * kullanılırken kullanılır . Min = 0, max = 1 yaptığınızda neden olduğunu göreceksiniz. Peterchen veya @ peter-mortensen bunu değiştirebilir mi?
davepc

17

Angry Shoe ve Peterchen'in mükemmel cevaplarını 2015'teki son teknolojiye kısa bir genel bakışla tamamlamak istiyorum:

Bazı iyi seçimler

randutils

randutilsKütüphane (sunum) basit bir arayüz ve (beyan) sağlam rastgele yetenekleri sunan ilginç bir yeniliktir. Projenize bağımlılık katması dezavantajlarına sahiptir ve yeni olduğu için kapsamlı bir şekilde test edilmemiştir. Her neyse, ücretsiz (MIT lisansı) ve yalnızca başlık olarak, denemeye değer olduğunu düşünüyorum.

Minimum örnek: bir kalıp silindiri

#include <iostream>
#include "randutils.hpp"
int main() {
    randutils::mt19937_rng rng;
    std::cout << rng.uniform(1,6) << "\n";
}

Kütüphaneye ilgi duyulmasa bile, web sitesi ( http://www.pcg-random.org/ ) genel olarak rastgele sayı oluşturma teması ve özel olarak C ++ kitaplığı hakkında birçok ilginç makale sunmaktadır.

Boost.Random

Boost.Random (belgeler) ilham kütüphane C++11's <random>, kiminle paylaşır çok arayüz. Teorik olarak aynı zamanda harici bir bağımlılık olmakla birlikte, Boostşimdiye kadar "yarı standart" kütüphane statüsüne sahiptir ve Randommodülü, kaliteli rasgele sayı üretimi için klasik seçim olarak kabul edilebilir. Çözüme göre iki avantajı vardır C++11:

  • daha taşınabilir, sadece C ++ 03 için derleyici desteğine ihtiyaç duyuyor
  • onun random_devicekaliteli tohumlama teklife kullandığı sisteme özel yöntemleri

Tek küçük kusur, modül teklifinin random_deviceyalnızca başlık olmaması, derleme ve bağlantı kurma zorunluluğudur boost_random.

Minimum örnek: bir kalıp silindiri

#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>

int main() {
    boost::random::random_device                  rand_dev;
    boost::random::mt19937                        generator(rand_dev());
    boost::random::uniform_int_distribution<>     distr(1, 6);

    std::cout << distr(generator) << '\n';
}

Minimal örnek işini iyi yaparken, gerçek programlar bir çift iyileştirme kullanmalıdır:

  • make mt19937a thread_local: jeneratör oldukça dolgun (> 2 KB) ve yığına tahsis edilmemesi daha iyi
  • mt19937birden fazla tam sayıya sahip çekirdek : Mersenne Twister büyük bir duruma sahiptir ve başlatma sırasında daha fazla entropiden yararlanabilir

Bazı çok iyi olmayan seçimler

C ++ 11 kitaplığı

En deyimsel çözüm olmasına rağmen, <random>kütüphane, temel ihtiyaçlar için bile arayüzünün karmaşıklığı karşılığında fazla bir şey sunmuyor. Kusur şudur std::random_device: Standart, çıktıları için herhangi bir minimum kaliteyi zorunlu kılmamaktadır ( entropy()geri dönüşler olduğu sürece 0) ve 2015 itibariyle MinGW (en çok kullanılan derleyici değil, ancak ezoterik bir seçim) her zaman 4minimum numuneye yazdıracaktır .

Minimum örnek: bir kalıp silindiri

#include <iostream>
#include <random>
int main() {
    std::random_device                  rand_dev;
    std::mt19937                        generator(rand_dev());
    std::uniform_int_distribution<int>  distr(1, 6);

    std::cout << distr(generator) << '\n';
}

Uygulama çürümüş değilse, bu çözüm Boost çözümüne eşdeğer olmalıdır ve aynı öneriler geçerlidir.

Godot'un çözümü

Minimum örnek: bir kalıp silindiri

#include <iostream>
#include <random>

int main() {
    std::cout << std::randint(1,6);
}

Bu basit, etkili ve temiz bir çözümdür. Sadece kusur, derlenmesi biraz zaman alacak - yaklaşık iki yıl, C ++ 17'nin zamanında piyasaya sürülmesi ve deneysel randintişlevin yeni Standartta onaylanması şartıyla . Belki o zamana kadar tohumlama kalitesindeki garantiler de artacaktır.

Daha kötüsü daha iyi çözüm

Minimum örnek: bir kalıp silindiri

#include <cstdlib>
#include <ctime>
#include <iostream>

int main() {
    std::srand(std::time(nullptr));
    std::cout << (std::rand() % 6 + 1);
}

Eski C çözümü zararlı olarak kabul edilir ve iyi nedenlerle (buradaki diğer cevaplara veya bu ayrıntılı analize bakın ). Yine de avantajları vardır: basit, taşınabilir, hızlı ve dürüsttür, bir anlamda elde edilen rastgele sayıların pek uygun olmadığı ve bu nedenle onları ciddi amaçlar için kullanmaya cazip gelmediği biliniyor.

Muhasebe trolü çözümü

Minimum örnek: bir kalıp silindiri

#include <iostream>

int main() {
    std::cout << 9;   // http://dilbert.com/strip/2001-10-25
}

9, normal bir kalıp silindiri için biraz alışılmadık bir sonuç olsa da, en hızlı, en basit, en önbellek dostu ve en taşınabilir çözüm olmayı başaran bu çözümdeki iyi niteliklerin mükemmel kombinasyonuna hayran olmak gerekir. 9'u 4 ile değiştirerek, her türden Zindan ve Ejderhalar ölürken mükemmel bir jeneratör elde ederken, sembol yüklü 1, 2 ve 3 değerlerinden kaçınıyor. Tek küçük kusur, Dilbert'in muhasebe trollerinin kötü huylu olması nedeniyle, bu program aslında tanımlanmamış davranışlara neden olur.


randutilsKütüphane şimdi PCG denir.
tay10r

10

Eğer RAND_MAX32767, kolayca bit sayısını iki katına çıkarabilir.

int BigRand()
{
    assert(INT_MAX/(RAND_MAX+1) > RAND_MAX);
    return rand() * (RAND_MAX+1) + rand();
}

Bunun işe yaradığını sanmıyorum. Sözde rasgele sayı üreteçleri tipik olarak deterministiktir. Örneğin, ilk randçağrı geri dönerse 0x1234ve ikincisi ise 0x5678, o zaman alırsınız 0x12345678. Başlayabileceğiniz tek sayı budur 0x1234, çünkü bir sonraki sayı her zaman olacaktır 0x5678. 32 bit sonuçlar alırsınız, ancak yalnızca 32768 olası sayıya sahipsiniz.
user694733

@ user694733 İyi bir rasgele sayı üretecinin oluşturabileceği çıktı sayısından daha büyük bir periyodu vardır, bu nedenle 0x1234'ün ardından her zaman 0x5678 gelmeyecektir.
Mark Ransom

9

Yapabiliyorsanız , Boost'u kullanın . Rasgele kitaplıkları konusunda iyi şanslar elde ettim .

uniform_int ne istersen yapmalısın.


Merseinne twister ile uniform_int üzerinde bazı çalışmalar yaptım ve maalesef belirli aralıklar için uniform_int tarafından döndürülen değerler beklediğim kadar tek tip değil. Örneğin uniform_int <> (0, 3) 1 veya 2'den daha fazla 0 üretme eğilimindedir
ScaryAardvark

@ScaryAardvark o zamanın kötü bir uygulaması gibi geliyor uniform_int. Tarafsız bir çıktı oluşturmak oldukça kolaydır, burada yöntemi gösteren çok sayıda soru vardır.
Mark Ransom

@Mark Ransom. Evet, tamamen katılıyorum.
ScaryAardvark

8

Hızla değil de rasgelelikle ilgileniyorsanız, güvenli bir rasgele sayı oluşturma yöntemi kullanmalısınız. Bunu yapmanın birkaç yolu var ... En kolay olanı OpenSSL'nin Rastgele Sayı Üreticisini kullanmaktır .

Ayrıca bir şifreleme algoritması ( AES gibi ) kullanarak kendinizinkini de yazabilirsiniz . Bir tohum ve bir IV seçerek ve ardından şifreleme işlevinin çıktısını sürekli olarak yeniden şifreleyerek. OpenSSL kullanmak daha kolay, ancak daha az erkeksi.


Herhangi bir üçüncü taraf kitaplığı kullanamıyorum, yalnızca C ++ ile sınırlandırıldım.
Anand

Sonra erkeksi rotaya gidin, AES veya başka bir şifreleme algoritması uygulayın.
SoapBox

2
RC4, kodlamak için önemsizdir ve tüm pratik amaçlar için yeterince rastgeledir (WEP hariç, ancak bu tamamen RC4'ün hatası değildir). Demek istediğim, inanılmaz derecede önemsiz bir kod. 20 satır falan. Wikipedia girişinde sahte kod var.
Steve Jessop

4
Neden üçüncü taraf kodunu kullanamıyorsunuz? Eğer bu bir ev ödevi sorusuysa, öyle söylemelisiniz, çünkü birçok insan bu durumda tam çözümler sunmak yerine yararlı ipuçları vermeyi tercih eder. Ödev değilse, "3. parti kodu yok" diyen adamı tekmele çünkü o bir aptal.
DevSolar

OpenSSL rand () işlevi belgelerine daha doğrudan bağlantı: openssl.org/docs/crypto/rand.html#
DevSolar

5

RAND_MAXÖzel derleyicinize / ortamınıza bakmalısınız . rand()Rastgele 16 bitlik bir sayı üretiyorsanız bu sonuçları görürsünüz . (32 bitlik bir sayı olacağını varsayıyorsunuz gibi görünüyor).

Cevabın bu olduğuna söz veremem, ama lütfen değerinizi RAND_MAXve çevreniz hakkında biraz daha fazla ayrıntı gönderin.



2

Bu kod değildir, ancak bu mantık size yardımcı olabilir.

static double rnd(void)
{
   return (1.0 / (RAND_MAX + 1.0) * ((double)(rand())) );
}

static void InitBetterRnd(unsigned int seed)
{
    register int i;
    srand( seed );
    for( i = 0; i < POOLSIZE; i++){
        pool[i] = rnd();
    }
}

 // This function returns a number between 0 and 1
 static double rnd0_1(void)
 {
    static int i = POOLSIZE-1;
    double r;

    i = (int)(POOLSIZE*pool[i]);
    r = pool[i];
    pool[i] = rnd();
    return (r);
}

2

Rakamların aralıkta tek tip olarak dağıtılmasını istiyorsanız, aralığınızı ihtiyacınız olan nokta sayısını temsil eden birkaç eşit bölüme bölmelisiniz. Ardından, her bölüm için bir min / maks olan rastgele bir sayı alın.

Başka bir not rand()olarak, aslında rastgele sayılar üretmekte pek iyi olmadığı için muhtemelen kullanmamalısınız . Hangi platformda koştuğunuzu bilmiyorum, ama muhtemelen arayabileceğiniz daha iyi bir işlev vardır random().


1

Bu [low, high), toplam aralık RAND_MAX'tan daha az olduğu sürece, kayan değerler kullanmadan aralık üzerinde tek tip bir dağılım sağlamalıdır.

uint32_t rand_range_low(uint32_t low, uint32_t high)
{
    uint32_t val;
    // only for 0 < range <= RAND_MAX
    assert(low < high);
    assert(high - low <= RAND_MAX);

    uint32_t range = high-low;
    uint32_t scale = RAND_MAX/range;
    do {
        val = rand();
    } while (val >= scale * range); // since scale is truncated, pick a new val until it's lower than scale*range
    return val/scale + low;
}

ve RAND_MAX'dan büyük değerler için şuna benzer bir şey istiyorsunuz:

uint32_t rand_range(uint32_t low, uint32_t high)
{
    assert(high>low);
    uint32_t val;
    uint32_t range = high-low;
    if (range < RAND_MAX)
        return rand_range_low(low, high);
    uint32_t scale = range/RAND_MAX;
    do {
        val = rand() + rand_range(0, scale) * RAND_MAX; // scale the initial range in RAND_MAX steps, then add an offset to get a uniform interval
    } while (val >= range);
    return val + low;
}

Bu kabaca std :: uniform_int_distribution'ın işleri nasıl yaptığıdır.


0

Doğası gereği, küçük bir rastgele sayı örneğinin tekdüze olarak dağıtılması gerekmez. Sonuçta rasgele. Rastgele bir sayı üreteci sürekli olarak gruplanmış gibi görünen sayılar üretiyorsa, muhtemelen bunda bir sorun olduğunu kabul ediyorum.

Ancak, rastgeleliğin mutlaka tek tip olmadığını unutmayın.

Düzenleme: Açıklığa kavuşturmak için "küçük örnek" ekledim.


"Tekdüze dağıtılmış" iyi tanımlanmış bir anlama sahiptir ve standart rastgele oluşturucular genellikle birbirine yaklaşır.
peterchen

Evet, haklısınız, rastgele sayı üreteçleri, zamanla dağıtımında genellikle tek tip çıktılar üretmelidir . Sanırım amacım, az sayıda örnekte (örnekte gösterildiği gibi 6) çıktının her zaman tek tip olmayacağıdır.
Kluge

Kluge haklı. Küçük bir numunedeki tekdüze dağılım, numunenin kesinlikle rastgele olmadığını gösterir .
Bill the Lizard

1
Bill, böyle bir şey olmadığını gösteriyor. Küçük numuneler çoğunlukla anlamsızdır, ancak RNG'nin tek tip olması gerekiyorsa ve çıktı tekdüze ise, bu neden tek tip olmayan küçük bir numuneden daha kötü?
Dan Dyer

2
Her iki şekilde de önemli dağılımlar rastlantısal olmayışı gösterir: Bence Bill sadece 6 eşit aralıklı sonucun da şüpheli olacağı anlamına geliyor. OP'de 6 değer, 32k / 4M aralığında veya istenen aralığın <% 1'inde yer alır. Bunun yanlış bir pozitif olma olasılığı, üzerinde tartışılamayacak kadar küçüktür.
Steve Jessop

0

1 ile 10 arasında bir sayı için man 3 rand tarafından verilen çözüm şudur:

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

Sizin durumunuzda şöyle olacaktır:

j = min + (int) ((max-min+1) * (rand() / (RAND_MAX + 1.0)));

Elbette, bu, diğer bazı mesajların işaret ettiği gibi mükemmel bir rastgelelik veya tekdüzelik değildir, ancak çoğu durum için bu yeterlidir.


1
Bu sadece dağıtım için yeniden düzenler görünür daha eşit, ancak (örneğin OP'ın vaka olarak) hatta büyük aralıkları için artık aslında değil
mölemeye Ördek

0

@Çözüm ((double) rand() / (RAND_MAX+1)) * (max-min+1) + min

Uyarı : Uzatma ve olası kesinlik hataları nedeniyle (RAND_MAX yeterince büyük olsa bile), [min, maks] cinsinden tüm sayıları değil, yalnızca eşit olarak dağıtılmış "bölmeler" oluşturabileceğinizi unutmayın.


@ Çözüm: Bigrand

Uyarı : Bunun bitleri iki katına çıkardığına dikkat edin, ancak yine de genel olarak aralığınızdaki tüm sayıları üretemeyecektir, yani, BigRand () kendi aralığı içindeki tüm sayıları üreteceği kesin değildir.


Bilgi : Yaklaşımınız (modulo), rand () aralığı, aralık aralığınızı aştığı ve rand () "tek tip" olduğu sürece "iyidir". En fazla ilk maksimum - minimum sayılar için hata 1 / (RAND_MAX +1) 'dir.

Ayrıca, rand () 'dan daha iyi ve daha fazla uygulama çeşidi sunan C ++ 11'deki yeni rastgele paket e'ye geçmeyi öneririm .


0

Bulduğum çözüm bu:

#include "<stdlib.h>"

int32_t RandomRange(int32_t min, int32_t max) {
    return (rand() * (max - min + 1) / (RAND_MAX + 1)) + min;
}

Bu, kavramsal olarak rand() / RAND_MAX0-1 arasında bir kayan nokta aralığı elde etmek ve bunu bir kovaya yuvarlamak için kullanılan çözümlere benzeyen bir kova çözümüdür . Bununla birlikte, tamamen tamsayı matematik kullanır ve değeri en yakın kovaya yuvarlamak için tamsayı bölmeli döşemeden yararlanır.

Birkaç varsayımda bulunur. İlk olarak, RAND_MAX * (max - min + 1)her zaman bir int32_t. Eğer RAND_MAXuygulamanız çok daha büyük bir RAND_MAX varsa 32767 ve 32 bit int hesaplamaları kullanılır ise, maksimum sen olabilir aralığı 32767 ise, daha büyük bir tamsayı (gibi kullanarak bu aşabiliriz int64_thesaplanması için). İkinci olarak, int64_tkullanılıyorsa ancak RAND_MAXhala 32767 ise, RAND_MAXsizden daha büyük aralıklarda olası çıktı sayılarında "delikler" almaya başlayacaksınız. Bu, muhtemelen ölçeklendirmeden elde edilen herhangi bir çözümle ilgili en büyük sorundur rand().

Yine de çok sayıda yineleme üzerinde yapılan testler, bu yöntemin küçük aralıklar için çok tekdüze olduğunu göstermektedir. Bununla birlikte, matematiksel olarak bunun bazı küçük önyargılara sahip olması ve aralık yaklaştığında muhtemelen sorunlar geliştirmesi mümkündür (ve muhtemelen) RAND_MAX. Kendiniz test edin ve ihtiyaçlarınızı karşılayıp karşılamadığına karar verin.


-1

Elbette, aşağıdaki kod size rastgele sayılar değil, sözde rastgele sayılar verir. Aşağıdaki kodu kullanın

#define QUICK_RAND(m,n) m + ( std::rand() % ( (n) - (m) + 1 ) )

Örneğin:

int myRand = QUICK_RAND(10, 20);

Aramalısın

srand(time(0));  // Initialize random number generator.

aksi takdirde sayılar neredeyse rastgele olmayacaktır.


1
Soru, tekdüze bir dağılım istiyor. Önerilen bu çözüm, tek tip bir dağılım sağlamayacaktır. Standart C ++ Kitaplığı, Sözde rasgele sayı oluşturma olanaklarına sahiptir . Bunlar do talep edilmesi halinde, homojen dağılım sağlar.
2019

-3

Bunu internette buldum. Bu çalışmalı:

DWORD random = ((min) + rand()/(RAND_MAX + 1.0) * ((max) - (min) + 1));

Lütfen onlara neye ihtiyacınız olduğunu açıklayın, orada PRNG'ler için tonlarca algoritma var. Ayrıca, yanıt göndermek yerine ana sorunuzu düzenlemeniz daha kolay olacaktır.
peterchen

Bu .. Bu formülle daha iyi dağıtılmış rasgele sayılar almak mümkün ... Benim için en uygun
Anand

4
Senin aralık RAND_MAX aşarsa, sonuç olabilir olmayacaktır muntazam olması. Yani, işlevinizi kaç kez çağırırsanız çağırın, aralıkta temsil edilmeyecek değerler vardır.
dmckee --- eski moderatör kedi yavrusu

4
Ayrıca, max ve min işaretsiz int ise ve min 0 ise ve max MAX_UINT ise ((max) - (min) +1) 0 olacak ve sonuç her zaman 0 olacaktır. Bu tür matematik yaparken taşmaya dikkat edin! Dmckee'nin belirttiği gibi, bu dağıtımı hedef aralığına kadar uzatır, ancak RAND_MAX benzersiz değerlerden fazlasını garanti etmez.
jesup
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.