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

 

我把MathRandomUniform 添加到我的脚本,以便进行比较。
,我把点的生成设置为1000000。为了估计分布,我把所有1000000个点显示在屏幕上,作为一个1000*1000的正方形。你击中一个点的次数越多,其颜色就越亮。
设置了1000万次RNG的重复,所以平均每个点应该被击中10次。

以下是结果。
RND。


我的RandomInteger的变体。


关于MathRand()。


MathRandomUniform()。


前两个RND是相当均匀的,3和4有空隙,即不均匀。
跳过的原因是MathRand分辨率=32767。 在乘数为1000000时,我们将得到跳过1000000/32767=30分。MathRandomUniform 图像上是相似的,可能,它有同样的30个

另一种变体。让我们把最大的数字设定为30000。
RND和 RandomInteger是相等的,就像它们是一百万 一样。MathRand和 MathRandomUniform 看起来像这样(有放大的块)。


没有空隙(黑点到位置30000)。但有些明显更亮。这是对30000/32767的不均匀取舍。每第11个点得到两倍的命中率。

统一的东西可以从 MathRand在最大3000的时候得到...4000.下面是3500的放大变体:


前两种变体在接近最大数字时,对于RandomInteger(其 分辨率 约为10亿)为1 亿,对于RND为40亿分辨率为4亿,-也会由于四舍五入而开始不均匀地分布

我已经附上了文件,你可以重复这个实验。
我决定为自己使用自己的函数,它比RND慢25%,但更紧凑和清晰。 我可以将分辨率提高到32767倍以上,见博客 中的代码。


请注意。
文章中的RND开发者指出

在种子=0时,该函数随机地改变初始值。

在每次重启时,我都设置种子=0,但有分布的图片在重启时没有变化。也就是说,这个说法是不正确的。从代码中你也看不出为什么它应该变成随机的。因此,为了随机初始化,必须将种子设置为一个随机数,例如seed=GetTickCount()

对于RandomInteger()函数,我们看到重新启动时的点的重新分配。如果设置了srand(0);,分布也会在重新启动时开始重复。所以为了让这个函数随机初始化,我需要不调用srand,或者使用MathSrand(GetTickCount()) 和时间戳。

附加的文件:
 

请记住,xor128通过了特殊的随机性测试,并且与标准的rand可以

关于交易、自动交易系统和策略测试的论坛

交易中的机器学习:理论、实践、交易及其他

Rorschach, 2020.04.19 22:18

我是个杂工,我把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种方法:W必须是2的幂,K是4的倍数

方法2:取消对srand的注释

方法2也应该对梅尔森漩涡起作用

 
Rorschach:

请注意,xor128通过了特殊的随机性测试,用一个标准的rand就可以



你显示每16个兰特调用。这种周期性的某种模式显现出来。
我正在使用所有连续的呼叫,每一个都是2个。从视觉上看,从我的照片上看,我没有看到与xor128的1000万次重复有任何区别。
 
Rorschach:

请注意,xor128通过了特殊的随机性测试,用一个标准的rand就可以


我试着把我自己的函数和xor128替换成你的函数

#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()也有一些除法。
用xor128更好,但有一些带状现象。

我不确定在正常使用中(不是16个中的1个)这些来自RandomInteger()的破折号会有什么影响...而且也不清楚他们的意思...

但我认为xor128更可靠。

 
Rorschach:

请注意,xor128通过了特殊的随机性测试,用一个标准的rand就可以


你有Mersen的代码吗?我曾在OpenCL的某个地方做过,但还没来得及把它移植到MQL5。比较一下会很有意思。

方法2也应适用于梅尔森的漩涡


 
Rashid Umarov:

你有Mersen的代码吗?我曾在OpenCL的某个地方做过,但还没来得及把它移植到MQL5。比较一下会很有意思。

在这里,我自己还没有使用过它。

 
elibrarius:

你显示的是每16次呼叫兰特。这种周期性的某种模式显现出来。
我正在使用所有连续的呼叫,每一个都是2个。 从视觉上看,从我的照片上看,我没有看到与xor128的1000万次重复有任何区别。

我不知道你的使用目的是什么,只是提醒你,可能会有意外的收获。

 
Rorschach:

在这里,我自己还没有使用过它。

谢谢!结果是代码比OpenCL上的要大。我将在某个时候尝试弄清楚。

 

对ter.ver的友好打击,整数的魔力,四舍五入,模块运算和双倍的技巧 :-)

如果f(x):: 在(0;N)上均匀分布 的整数,并不意味着g(x)=N/(double)f(x)会在(0;1)上均匀分布,也会通过所有测试。

关于g(x)=f(x)mod M也是如此,但N mod M=0是个罕见的例外。

PS/顺便说一句,g(x)=f(x)/(double)N也不会是均匀的。将会有分裂的焦点。也就是说,图中会出现摩尔纹。

PPS/对于随机性的视觉 "测试",除了模数钝方之外,还应用了 "乌拉姆蜗牛 "的变种。

 
Rorschach:

在这里,我自己还没有使用过它。

从这个代码中测量了CRandomMersenne和CRandomMother的性能。它们的速度比xor128慢3倍。这不是很令人满意。但根据你的代码,在你打破GSF的地方,它们看起来比xor128(没有竖条)更好。