CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Mersenne Twister z 2 granicami

Mersenne Twister z 2 granicami

dział ogólny

Mersenne Twister z 2 granicami

Nowy postprzez oneiro » niedziela, 24 lutego 2013, 23:31

Witam,

Potrzebuję zrobić generator liczb pseudolosowych albo mający ograniczenia z dołu i góry. Maksymalny przedział liczy to:

0 <= RAND <= 1

natomiast w większości przypadków będzie to

A [<=,<] RAND [<=,<] B

gdzie A<B oraz należą do przedziału (0,1). RAND oczywiście jest liczbą dziesiętną.
Ściągnąłem kod Mersenne Twister i mam tam opcje generowanie liczb z przedziałów
[0,1]
(0,1]
[0,1)
(0,1)

Mogę ograniczać liczby poprzez IF, ale mija się to z celem (dla dostatecznie wąskich przedziałów więcej czasu zajmie mi generowanie liczby niż właściwe obliczenia)
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Mersenne Twister z 2 granicami

Nowy postprzez Mironas » poniedziałek, 25 lutego 2013, 11:05

Na początku programu (np. w OnCreate formy) daj:
KOD cpp:     UKRYJ  
  randomize();  // Uruchomienie generatora liczb losowych
 


Pojedynczą liczbę generujesz:
KOD cpp:     UKRYJ  
  int x = random(max);  // generuje liczbę całkowitą z zakresu 0÷(max-1)
 


I parę wskazówek:
Jeśli potrzebujesz wygenerować liczbę z zakresu 10÷20 to najpierw generujesz z zakresu 0÷10 a potem dodajesz 10.
Jeśli potrzebujesz liczbę zmiennoprzecinkową (float) z zakresu 0.0÷1.0 to generujesz liczbę w zakresie 0÷1000, zapisujesz do zmiennej float a na koniec dzielisz przez 1000.0

Powyższe wskazówki powinny Ci wystarczyć do przygotowania takiego generatora jaki potrzebujesz.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Mersenne Twister z 2 granicami

Nowy postprzez Cyfrowy Baron » poniedziałek, 25 lutego 2013, 18:34

Mironas napisał(a):Jeśli potrzebujesz wygenerować liczbę z zakresu 10÷20 to najpierw generujesz z zakresu 0÷10 a potem dodajesz 10.


Można tak, ale można również skorzystać z funkcji RandomRange(int AFrom, int ATo) - gdzie zmienna AFrom określa początkowy zakres losowania (włączenie), a ATo końcowy zakres losowania, przy czym jeżeli podamy np. 20 to zakres losowania kończy się na 19. Generatorem liczb dla RandomRange jest Randomise() - pisany z wielkiej litery nie z małej. Generator uruchamiamy tylko raz np. na starcie aplikacji w zdarzeniu OnCreate lub w konstruktorze klasy okna głównego. Jeżeli losowanie odbywa się na innym formularzu niż główny to generator i tak uruchamiamy raz na formularzu głównym. Generatora nie da się zatrzymać.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Mersenne Twister z 2 granicami

Nowy postprzez oneiro » poniedziałek, 25 lutego 2013, 20:12

Dziękuję Wam, na podstawie waszych postów znalazłem to czego szukałem (widać, źle wcześniej szukałem)

KOD cpp:     UKRYJ  
//To mi generuje od 0.0 do 1.0 włącznie:
float r = (float)rand()/(float)RAND_MAX;

//To generuje od 0.0 to górnej granicy X:
float r2 = (float)rand()/((float)RAND_MAX/X);

//To generuje od dolnej granicy LO do górnej HI
float r3 = LO + (float)rand()/((float)RAND_MAX/(HI-LO));
 


Znalazłem też fajną bibliotekę Boost.Random
KOD cpp:     UKRYJ  
  boost::mt19937 rng;
  boost::uniform_real<float> u(min, max);
  boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
  double wynik=gen();
 


Zależmy mi na MT (lub WELL - Well Equidistributed Long-period Linear), dlatego też chyba skorzystam z Boost.Random
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Mersenne Twister z 2 granicami

Nowy postprzez Cyfrowy Baron » poniedziałek, 25 lutego 2013, 21:08

Funkcja rand() wymaga uruchomienia generatora srand. Jeżeli nie uruchomisz generatora to program zawsze będzie losował te same liczby:

KOD cpp:     UKRYJ  
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */

 srand ( time(NULL) );


Makro RAND_MAX to po prostu wartość: 32767, dlatego ten sam efekt uzyskasz za pomocą funkcji Random:

KOD cpp:     UKRYJ  
Randomize(); /* uruchomienie generatora */

float x = 32767;
float r = Random(x) / x;


oneiro napisał(a)://To generuje od dolnej granicy LO do górnej HI


Podobnie jak to:

KOD cpp:     UKRYJ  
Randomize(); /* uruchomienie generatora */

float x = 32767;
float r = RandomRange(x*2, x*4) / x;


w powyższym przykładzie zakres to: dolny = 2 (x*2); górny = 4 (x*4). Po prostu pierwszy argument funkcji to x=32767 pomnożony przez wartość dolną, a drugi adekwatnie pomnożony przez wartość górną. Wartość x nie musi się równać dokładnie 32767, wystarczy, że będzie większa od losowanego zakresu. Wszystko zależy od tego jak dokładna ma być wartość dziesiętna.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox


Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 46 gości