¿Cómo genera MathRand() los valores? - página 2

 
yu-sha:

Por favor, dime cómo MathRand() obtiene los valores.

¿Podemos esperar que MathRand() se distribuya uniformemente en el rango declarado?

este es un ejemplo, por supuesto hay otros algoritmos más complejos...

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

Se requiere una función RNG con el número Int de 0 a cualquier valor.

Como el valor máximo de Int =2.147.483.647, calculamos hasta él.

Hemos obtenido esta función. Creo que la distribución es 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);
}
 
El artículo tiene un generador a 4294967295
 
Rorschach:
El artículo tiene un generador de hasta 4294967295

El Alglib SB tiene un oscilador de alta precisión

UPD: Lo he probadohttps://www.mql5.com/ru/forum/324066#comment_13500222 , parece que funciona, pero no hay documentación para Alglib en MQL5, deberías leerla en la web de Alglib

 
Rorschach:
El artículo tiene un generador a 4294967295

Gracias, lo he comparado en términos de velocidad de cálculo.
Mi función en rand() estándar resultó ser 2 veces más lenta. Aunque el código parecía mucho más sencillo...


 
Igor Makanu:

El Alglib SB tiene un oscilador de alta precisión

UPD: Lo he probadohttps://www.mql5.com/ru/forum/324066#comment_13500222 , parece que funciona, pero no hay documentación para Alglib en MQL5, deberías leerla en la web de Alglib

Lo he visto pero lo quiero sin alglib. Además, esa función tiene un montón de */%. No he comparado su velocidad ya que obviamente es más lenta. El generador del artículo funciona con cambios de bits: es más rápido.

 

Reescribí mi función para optimizar la velocidad:

int RandomInteger(int max_vl){return (int)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);}//случайное Int от 0 до  Max Int
La distribución resultó ser uniforme. Vea las imágenes del experimento en el blog https://www.mql5.com/ru/blogs/post/735953

He vuelto a escribir el RNG del artículo.
Descarté cosas innecesarias y esto es lo que obtuve:

//если из 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;}
   };
};

La distribución también resultó ser uniforme.

He comparado la velocidad de ambas funciones, la original del artículo y la simple MathRand():


El original del artículo rnd.Rand_01() - 602 ms.
Acortado según el artículo rnu.Rand_01() - 596 ms
Mi versión optimizada de RandomInteger() - 840 ms (la versión antigua 1200 ms, es decir, un 25% más rápida)
Sólo por MathRand() - 353 ms (el más rápido, pero la distribución será desigual. Si el rango de números requerido es mayor que 32767, el resultado será omitido. Si es inferior a 32767, por ejemplo i=31111. entonces el redondeo será más frecuente en algunos puntos).

Aprovecha)
Rand 0 ... Max Int с равномерным распределением
Rand 0 ... Max Int с равномерным распределением
  • www.mql5.com
Потребовалась функция ГСЧ с гнерацией числа Int от 0 до любого значения.Получилась такая функция. Думаю распределение получилось равномерным. int RandomInteger(int max_vl){return
 
elibrarius:
Interesante. Encontré otro aleatorio en la biblioteca estándar, pero es poco probable que sea mejor.
 

¿Por qué complicar tanto las cosas?

Puedes hacerlo así (a grandes rasgos):

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

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

Y si quieres jugar o ver lo que muestra, puedes hacer esto:

int x=1;

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

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

Comment(x);

y ver cómo cambia los valores.

 
elibrarius:

He reescrito mi función para optimizar la velocidad:

La distribución es uniforme. Vea las imágenes del experimento en el blog https://www.mql5.com/ru/blogs/post/735953

He vuelto a escribir el RNG del artículo.
Descarté cosas innecesarias y eso es lo que tengo:

La distribución también resulta ser uniforme.

Lo he comparado con la distribución de la ayuda, no veo ninguna diferencia

Archivos adjuntos: