Come genera i valori MathRand()? - pagina 3

 

Ho aggiuntoMathRandomUniform al mio script per il confronto.
Ho impostato la generazione dei punti a 1000000. Per stimare la distribuzione, mostro tutti i 1000000 punti sullo schermo come un quadrato 1000*1000. Più volte si colpisce un punto, più luminoso è il suo colore.

Ho impostato 10 milioni di ripetizioni di RNG, quindi in media ogni punto dovrebbe essere colpito 10 volte.

Ecco i risultati:
RND:


La mia variante di RandomInteger:


Su MathRand():


Su MathRandomUniform():


I primi due RND sono abbastanza pari, il 3 e il 4 hanno dei vuoti, cioè non sono pari.
I salti sono dovuti alla risoluzione MathRand = 32767. Con un moltiplicatore di 1000000 otterremo salti 1000000/32767=30 punti. MathRandomUniform è simile per immagine, probabilmente, ha gli stessi 30 salti.

Un'altra variante. Impostiamo il numero massimo 30000.
RND e RandomInteger sono uguali, come se fossero un milione .MathRand e MathRandomUniform si presenta così (con chunk ingrandito):


Non ci sono lacune (punti neri fino alla posizione 30000). Ma alcuni sono notevolmente più luminosi. Questo è un arrotondamento irregolare di 30000/32767. Ogni 11° punto riceve il doppio dei colpi.

Qualcosa di uniforme può essere ottenuto da MathRand a un massimo di 3000... 4000. Ecco una variante allargata per 3500:


Le prime due varianti quando si avvicinano al numero massimo a 100 milioni perRandomInteger (che ha risoluzione circa 1 miliardo) e 400 milioni a 4 miliardi di risoluzione per RND, - cominceranno anche a distribuirsi in modo non uniforme a causa dell'arrotondamento.

Ho allegato il file, potete ripetere l'esperimento.
Ho deciso di usare la mia funzione per me stesso, è il 25% più lento di RND ma più compatto e chiaro, posso aumentare la risoluzione fino a 32767 volte di più, vedi codice nel blog.


Nota:
Lo sviluppatore RND dell'articolo ha sottolineato che

A seed=0 la funzione cambia i valori iniziali in modo casuale.

Ad ogni riavvio, ho impostato seed=0, ma l'immagine con le distribuzioni non cambia al riavvio. Cioè l'affermazione non è corretta. Non si vede nemmeno dal codice perché dovrebbe diventare casuale. Quindi, per inizializzare in modo casuale, seed deve essere impostato su un numero casuale, per esempio seed=GetTickCount();

Per la funzione RandomInteger(), vediamo la ridistribuzione dei punti al riavvio. Se srand(0); è impostato, la distribuzione inizia a ripetersi anche al riavvio. Quindi, affinché questa funzione si inizializzi in modo casuale, ho bisogno o di non chiamare srand, o di usare MathSrand(GetTickCount()) con anche il timestamp.

File:
 

Tenete presente che xor128 supera speciali test di casualità, e con rand standard può essere

Forum sul trading, sistemi di trading automatico e test di strategia

L'apprendimento automatico nel trading: teoria, pratica, trading e oltre

Rorschach, 2020.04.19 22:18

Sono un tuttofare, ho rotto l'RSCH(((

#include <Canvas\Canvas.mqh>
void OnStart()
  {CCanvas C;
   int h=1024;
   int w=2048;
   C.CreateBitmapLabel("11",100,100,w,h);
   for(int y=0;y<h;y++)
     {//srand(GetMicrosecondCount());
      for(int x=0;x<w;x++)
        {uchar c=0;
         for(int k=0;k<16;k++)
           {c=uchar(255.*rand()/32767.);
           }
         C.PixelSet(x,y,ARGB(255,c,c,c));
        }
     }
   C.Update();

1 modo: w deve essere una potenza di 2, k è un multiplo di 4

Modo 2: decommentare srand

Il metodo 2 dovrebbe funzionare anche sul vortice Mersen

 
Rorschach:

Si noti che xor128 supera speciali test di casualità, e con un rand standard può essere



Si visualizza ogni 16° chiamata rand. Da questa periodicità emerge una sorta di schema.
Sto usando tutte le chiamate consecutive di 2 in ciascuna. Visivamente, dalle mie foto, non vedo alcuna differenza con xor128 per 10 milioni di ripetizioni.
 
Rorschach:

Si noti che xor128 supera speciali test di casualità, e con un rand standard può essere


Ho provato a sostituire la mia funzione e xor128 nella tua funzione

#include <Canvas\Canvas.mqh>
void OnStart()
  {CCanvas C;
  RND rn;   rn.SRand(0);
   int h=1024;
   int w=2048;
   C.CreateBitmapLabel("11",100,100,w,h);
   for(int y=0;y<h;y++)
     {//srand(GetMicrosecondCount());
     rn.SRand(GetMicrosecondCount());
      for(int x=0;x<w;x++)
        {uchar c=0;
         for(int k=0;k<16;k++)
           //{c=uchar(255.*rand()/32767.);}
           //{c=uchar(255.*RandomInteger(1073741824)/1073741824.0); }
           {c=(uchar)(255.0*rn.Rand_01()); }
         C.PixelSet(x,y,ARGB(255,c,c,c));
        }
     }
   C.Update();
   }
  
   int RandomInteger(int max_vl){return (int)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);}//случайное Int от 0 до  1073741824


//если из define переместить в код RNDUint, то скорость работы увеличится на 30% для 10 млн повторов с 600 мс до 850 мс. Это почти как RandomInteger()

#define xor32  xx=xx^(xx<<13);xx=xx^(xx>>17);xx=xx^(xx<<5)
#define xor128 t=(x^(x<<11));x=y;y=z;z=w;w=(w^(w>>19))^(t^(t>>8))
#define inidat x=123456789;y=362436069;z=521288629;w=88675123;xx=2463534242

class RND{
protected:
   uint      x,y,z,w,xx,t;
public:
      RND(void){inidat;};
    ~RND(void){};
   uint      RandMaxUI(uint max_v)   {xor128;return((uint)MathFloor((double)w/UINT_MAX*max_v));};//равномерное распределение на отрезке [0,max_v]. uint
   int       RandMaxI(int max_v)     {xor128;return((int) MathFloor((double)w/UINT_MAX*max_v));};//равномерное распределение на отрезке [0,max_v]. int
   uint      Rand()    {xor128;return(w);};//равномерное распределение на отрезке [0,UINT_MAX=4294967295].
   double    Rand_01() {xor128;return((double)w/UINT_MAX);};//равномерное распределение на отрезке [0,1].
   void      Reset()   {inidat;};//сброс всех исходных значений в первоначальное состояние.
   void      SRand(uint seed)  {//установка новых исходных значений генератора.seed= [0,UINT_MAX=4294967295]. При seed=0 функция меняет начальные значения случайным образом.
      int i;if(seed!=0){xx=seed;}for(i=0;i<16;i++){xor32;}xor32;x=xx;xor32;y=xx;xor32;z=xx;xor32;w=xx;for(i=0;i<16;i++){xor128;}
   };
};


RandomInteger() ha anche alcune divisioni.
Meglio con xor128, ma c'è un po' di banding:

Non sono sicuro che nell'uso normale (non 1 di 16) questi trattini di RandomInteger() abbiano qualche effetto... E non è chiaro cosa vogliano dire...

Ma penso che xor128 sia più affidabile.

 
Rorschach:

Si noti che xor128 supera speciali test di casualità, e con un rand standard può essere


Hai il codice di Mersen? L'avevo su OpenCL da qualche parte, ma non sono riuscito a portarlo su MQL5. Sarebbe interessante confrontare.

Il metodo 2 dovrebbe funzionare anche sul vortice di Mersen


 
Rashid Umarov:

Hai il codice di Mersen? L'avevo su OpenCL da qualche parte, ma non sono riuscito a portarlo su MQL5. Sarebbe interessante confrontare.

Ecco, io stesso non l'ho usato.

 
elibrarius:

Si visualizza ogni 16° chiamata rand. Da questa periodicità emerge una sorta di schema.
Sto usando tutte le chiamate consecutive di 2 in ciascuna. Visivamente, dalle mie foto, non vedo alcuna differenza con xor128 per 10 milioni di ripetizioni.

Non so quale sia il vostro scopo d'uso, solo un avvertimento che potrebbero esserci delle sorprese.

 
Rorschach:

Ecco, io stesso non l'ho usato.

Grazie! Il codice è risultato essere più grande che su OpenCL. Prima o poi cercherò di capirlo.

 

un colpo amichevole su ter.ver, la magia dei numeri interi, l'arrotondamento, l'aritmetica modulare e i trucchi del doppio :-)

se f(x) :: intero uniformemente distribuito su (0;N], non significa che g(x)=N/(doppio)f(x) sarà uniformemente distribuito su (0;1] e supererà anche tutti i test.

Lo stesso vale per g(x) = f(x) mod M, con la rara eccezione N mod M = 0.

PS/ a proposito e g(x)=f(x)/(doppio)N non sarà nemmeno uniforme. Ci saranno punti focali di divisione. Cioè, le trame mostreranno il moiré.

PPS/ per un "test" visivo per la casualità, oltre al quadrato smussato modulo, si applicano variazioni della "chiocciola di Ulam

 
Rorschach:

Ecco, io stesso non l'ho usato.

Misurate le prestazioni di CRandomMersenne e CRandomMother da questo codice. Sono 3 volte più lenti di xor128. Questo non è molto soddisfacente. Ma secondo il tuo codice, dove hai rotto il GSF, sembrano migliori di xor128 (senza la barra verticale).