Come genera i valori MathRand()? - pagina 2

 
yu-sha:

Per favore, ditemi come MathRand() ottiene i valori.

Possiamo aspettarci che MathRand() sia distribuito uniformemente nell'intervallo dichiarato?

ecco un esempio, naturalmente ci sono altri algoritmi più complessi...

sorgente rand.c :

/***
*rand.c - random number generator
*
*       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines rand(), srand() - random number generator
*
*******************************************************************************/

#include <cruntime.h>
#include <mtdll.h>
#include <stddef.h>
#include <stdlib.h>

#ifndef _MT
static long holdrand = 1 L;
#endif  /* _MT */

/***
*void srand(seed) - seed the random number generator
*
*Purpose:
*       Seeds the random number generator with the int given.  Adapted from the
*       BASIC random number generator.
*
*Entry:
*       unsigned seed - seed to seed rand # generator with
*
*Exit:
*       None.
*
*Exceptions:
*
*******************************************************************************/

void __cdecl srand (
       unsigned int seed
       )
{
#ifdef _MT

       _getptd()->_holdrand = (unsigned long)seed;

#else  /* _MT */
       holdrand = (long)seed;
#endif  /* _MT */
}


/***
*int rand() - returns a random number
*
*Purpose:
*       returns a pseudo-random number 0 through 32767.
*
*Entry:
*       None.
*
*Exit:
*       Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl rand (
       void
       )
{
#ifdef _MT

       _ptiddata ptd = _getptd();

       return( ((ptd->_holdrand = ptd->_holdrand * 214013 L
           + 2531011 L) >> 16) & 0x7fff );

#else  /* _MT */
       return(((holdrand = holdrand * 214013 L + 2531011 L) >> 16) & 0x7fff);
#endif  /* _MT */
}
 

È necessaria una funzione RNG con il numero Int da 0 a qualsiasi valore.

Poiché il valore massimo di Int =2.147.483.647, calcoliamo fino ad esso.

Abbiamo ottenuto questa funzione. Credo che la distribuzione sia uniforme.

int RandomInteger(int max_vl){//случайное Int от 0 до  Max Int
        //srand(0);//если нужна повторяемость.  MathSrand(GetTickCount()) если нужна неповторяемость
        int r=MathRand();// от 0 до 32767.
        double k=32767.0;
        if(max_vl>32767){
                r=r+MathRand()*32767;//0...32767 + 0.. 32767*32767(с шагом 32767)  max=1073709056 > 1 mlrd
                k=k*k;
                if(max_vl>1073709056){// int type max alue =2 147 483 647 > 2 mlrd
                        r=r*2+MathRand()%2;//0...2 147 483 647 > to max int number c шагом 2 + (0 или 1)
                        k=k*2;
                }
        }
        return (int)MathFloor(r/k*max_vl);
}
 
L'articolo ha un generatore a 4294967295
 
Rorschach:
L'articolo ha un generatore fino a 4294967295

Alglib SB ha un oscillatore ad alta precisione

UPD: ho provatohttps://www.mql5.com/ru/forum/324066#comment_13500222 , sembra funzionare, ma non c'è documentazione per Alglib in MQL5, dovresti leggerla sul sito web di Alglib

 
Rorschach:
L'articolo ha un generatore a 4294967295

Grazie, l'ho confrontato in termini di velocità di calcolo.
La mia funzione su rand() standard è risultata essere 2 volte più lenta. Anche se il codice sembrava molto più semplice...


 
Igor Makanu:

Alglib SB ha un oscillatore ad alta precisione

UPD: ho provatohttps://www.mql5.com/ru/forum/324066#comment_13500222 , sembra funzionare, ma non c'è documentazione per Alglib in MQL5, dovresti leggerla sul sito web di Alglib

L'ho visto ma lo voglio senza alglib. Inoltre, quella funzione ha un sacco di */%. Non ho confrontato la sua velocità perché è ovviamente più lento. Il generatore dell'articolo funziona con spostamenti di bit - è più veloce.

 

Ho riscritto la mia funzione per ottimizzare la velocità:

int RandomInteger(int max_vl){return (int)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);}//случайное Int от 0 до  Max Int
La distribuzione è risultata essere uniforme. Vedi le immagini dell'esperimento nel blog https://www.mql5.com/ru/blogs/post/735953

Ho riscritto l'RNG dall'articolo.
Ho scartato le cose inutili e questo è quello che ho ottenuto:

//если из define переместить в код RNDUint, то скорость работы увеличится на 30% для 10 млн повторов с 600 мс до 850 мс
#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 RNDUint{
protected:
   uint      x,y,z,w,xx,t;
public:
        RNDUint(void){inidat;};
        ~RNDUint(void){};
   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;}
   };
};

Anche la distribuzione è risultata essere uniforme.

Ho confrontato la velocità di entrambe le funzioni, originale dall'articolo e semplice MathRand():


L'originale dall'articolo rnd.Rand_01() - 602 ms.
Accorciato secondo l'articolo rnu.Rand_01() - 596 ms
La mia versione ottimizzata di RandomInteger() - 840 ms (vecchia versione 1200 ms, cioè il 25% più veloce)
Solo da MathRand() - 353 ms (il più veloce, ma la distribuzione non sarà uniforme. Se la gamma di numeri richiesti è maggiore di 32767, il risultato sarà saltato. Se meno di 32767, per esempio i=31111. allora l'arrotondamento sarà più frequente in alcuni punti).

Approfittane)
Rand 0 ... Max Int с равномерным распределением
Rand 0 ... Max Int с равномерным распределением
  • www.mql5.com
Потребовалась функция ГСЧ с гнерацией числа Int от 0 до любого значения.Получилась такая функция. Думаю распределение получилось равномерным. int RandomInteger(int max_vl){return
 
elibrarius:
Interessante. Ho trovato un altro random nella libreria standard, ma è improbabile che sia migliore.
 

Perché complicare così tanto le cose?

Puoi farlo in questo modo (approssimativamente):

if (MathRand()%100>50) => Buy

if (MathRand()%100<50) => Sell

E se volete giocare o vedere cosa mostra, potete fare così:

int x=1;

if (MathRand()%100>50) x=1;

if (MathRand()%100<50) x=2;

Comment(x);

e vedere come cambia i valori.

 
elibrarius:

Ho riscritto la mia funzione per ottimizzare la velocità:

La distribuzione è uniforme. Vedi le immagini dell'esperimento sul blog https://www.mql5.com/ru/blogs/post/735953

Ho riscritto l'RNG dall'articolo.
Ho scartato le cose inutili e questo è quello che ho ottenuto:

Anche la distribuzione risulta essere uniforme.

L'ho confrontato con la distribuzione della guida, non vedo alcuna differenza