MathRand()是如何生成数值的? - 页 2

 
yu-sha:

请告诉我MathRand()如何取值。

我们能指望MathRand()在声明的范围内均匀分布吗?

这里是一个例子,当然还有其他更复杂的算法...

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

需要一个RNG函数,数字Int从0到任意值。

由于Int的最大值=2,147,483,647,所以我们计算到它。

我们已经得到了这个函数。我认为分布是均匀的

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);
}
 
该文章 有一个发电机到4294967295
 
Rorschach:
该文章 有一个发电机高达4294967295

Alglib SB有一个高精度的振荡器

UPD: 我试了一下https://www.mql5.com/ru/forum/324066#comment_13500222 , 似乎可以工作,但MQL5中没有Alglib的文档,你应该在Alglib网站上阅读。

 
Rorschach:
该文章 有一个发电机到4294967295

谢谢,我从计算速度方面进行了比较。
我在标准rand()上的函数结果是慢了2倍。虽然代码看起来简单多了...


 
Igor Makanu:

Alglib SB有一个高精度的振荡器

UPD: 我试了一下https://www.mql5.com/ru/forum/324066#comment_13500222 , 似乎可以工作,但MQL5中没有Alglib的文档,你应该在Alglib网站上阅读。

我看到了,但我希望它不含alglib。此外,该函数有很多*/%。我没有比较它的速度,因为它显然更慢。 文章中的生成器可以用位移来工作--它更快。

 

重写了我的函数以优化速度。

int RandomInteger(int max_vl){return (int)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);}//случайное Int от 0 до  Max Int
结果发现分布是均匀的。请看博客中的实验图片https://www.mql5.com/ru/blogs/post/735953

我重新写了文章中的RMS。
我丢弃了不必要的东西,这就是我得到的东西。

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

分配结果也是平等的。

我比较了两个函数的速度,文章中的原始函数和简单的MathRand()。


文章中的原文rnd.Rand_01() - 602 ms
根据rnu.Rand_01()文章缩短 - 596 ms
我的优化版RandomInteger() - 840毫秒(旧版1200毫秒,即快25%)。
仅仅通过MathRand() - 353 ms(最快,但分布会不均匀。如果要求的数字范围大于32767,结果将被跳过。如果小于32767,例如i=31111.那么四舍五入会更频繁地出现在某些点上)。

利用优势)
Rand 0 ... Max Int с равномерным распределением
Rand 0 ... Max Int с равномерным распределением
  • www.mql5.com
Потребовалась функция ГСЧ с гнерацией числа Int от 0 до любого значения.Получилась такая функция. Думаю распределение получилось равномерным. int RandomInteger(int max_vl){return
 
elibrarius:
有趣的是。 标准库中 找到了另一个随机数 ,但它不太可能更好。
 

为什么要把事情搞得这么复杂?

你可以这样做(大致上说)。

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

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

如果你想玩一玩,或者看看它显示了什么,你可以这样做。

int x=1;

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

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

Comment(x);

并看看它是如何改变数值的。

 
elibrarius:

我已经重写了我的函数以优化速度。

分布是均匀的。请看博客上的实验图片https://www.mql5.com/ru/blogs/post/735953

我重写了文章中的RNG。
我丢弃了不必要的东西,这就是我得到的东西。

分布结果也是均匀的。

我把它与帮助中的分布进行了比较,我没有看到任何区别。

附加的文件: