MathRand()는 어떻게 값을 생성합니까? - 페이지 3

 

내 스크립트에서 비교를 위해 추가됨 MathRandomUniform
포인트 생성을 1000000까지 설정했습니다. 분포를 평가하기 위해 화면에 1000000 포인트를 모두 1000 * 1000 정사각형 형태로 표시합니다. RNG가 포인트에 더 많이 닿을수록 색상이 더 밝아집니다.

나는 RNG의 1000만 반복을 설정 했습니다. 평균적으로 각 포인트는 10번 맞아야 합니다.

결과는 다음과 같습니다.
RND:


내 RandomInteger 옵션:


MathRand():


MathRandomUniform ():


처음 두 개의 RNG는 간격이 있는 3과 4로 매우 균일합니다. 고르지 않은.
갭은 MathRand = 32767 해상도로 인한 것입니다. 1000000의 승수를 사용하면 1000000/32767=30 포인트의 갭이 생깁니다. MathRandomUniform 은 그림에서 유사하며 분명히 30단위의 동일한 간격입니다.

또 다른 변종. 최대 수를 30000으로 설정하겠습니다.
RND와 RandomInteger는 백만과 마찬가지로 균일합니다. 수학 랜드 및 MathRandomUniform 다음과 같이 보입니다(더 큰 조각 포함).


간격이 없습니다(위치 30000까지의 검은색 점). 그러나 일부는 눈에 띄게 밝습니다. 이것은 30000/32767의 반올림 불균일입니다. 11번째 포인트마다 2배의 안타를 얻습니다.

에서 균일한 것을 얻을 수 있습니다. MathRand는 최대 3000...4000입니다. 다음은 3500에 대한 확대 버전입니다.


RandomInteger 의 경우 최대 수가 1억(약 10억 의 해상도 를 가짐)의 경우 1억에 도달하고 RND의 경우 40억의 해상도에서 4억에 도달하는 처음 두 옵션도 반올림으로 인해 고르지 않게 분포되기 시작합니다.

파일이 첨부되어 있으므로 실험을 반복할 수 있습니다.
나는 내 자신의 기능을 사용하기로 결정했습니다. RND보다 25% 느리지만 더 컴팩트하고 명확하면 해상도를 32767배 더 높일 수 있습니다. 블로그 의 코드를 참조하세요.


메모:
기사의 RND 개발자는 다음과 같이 지적했습니다.

seed=0일 때 함수는 초기 값을 무작위로 변경합니다.

다시 시작할 때마다 seed = 0으로 설정했지만 다시 시작하는 동안 분포가 있는 그림은 변경되지 않습니다. 저것들. 진술이 잘못되었습니다. 코드는 또한 그것이 무작위가 되어야 하는 이유를 보여주지 않습니다. 저것. 임의 초기화의 경우 시드를 임의의 숫자로 설정해야 합니다(예: seed= GetTickCount();

RandomInteger() 함수의 경우 다시 시작할 때 포인트의 재분배가 표시됩니다. srand(0); 그런 다음 다시 시작할 때 배포도 반복되기 시작합니다. 저것들. 이 함수의 경우 임의 초기화의 경우 srand를 호출하지 않거나 MathSrand(GetTickCount()) 타임스탬프와 함께 호출해야 합니다.

파일:
 

xor128은 임의성에 대한 특별 테스트를 통과했으며 표준 rand를 사용하면 다음과 같이 될 수 있습니다.

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

거래에서의 머신 러닝: 이론, 실습, 거래 등

로르샤흐 , 2020.04.19 22:18

나는 핸들러, RNG는 파산(((

 #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는 Mersen Vortex에서도 작동해야 합니다.

 
Rorschach :

xor128은 임의성에 대한 특별 테스트를 통과했으며 표준 rand를 사용하면 다음과 같이 될 수 있습니다.



16번째 호출마다 rand에 매핑합니다. 이 주기성에서 그 규칙성이 무엇인지 보여줍니다.
나는 모든 통화를 연속으로 사용합니다. 각 통화는 2번입니다. 시각적으로 내 사진에 따르면 1000만 반복에 대해 xor128과 차이가 없습니다.
 
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를 사용하면 다음과 같이 될 수 있습니다.


메르센 코드가 있습니까? OpenCL의 어딘가에 손이 닿지 않아 MQL5로 전송할 수 없었습니다. 비교해보는 것도 흥미로울 것이다.

방법 2는 Mersen Vortex에서도 작동해야 합니다.


 
Rashid Umarov :

메르센 코드가 있습니까? OpenCL의 어딘가에 손이 닿지 않아 MQL5로 전송할 수 없었습니다. 비교해보는 것도 흥미로울 것이다.

여기 , 나는 그것을 직접 사용하지 않았습니다.

 
elibrarius :

16번째 호출마다 rand에 매핑합니다. 이 주기성에서 그 규칙성이 무엇인지 보여줍니다.
나는 모든 통화를 연속으로 사용합니다. 각 통화는 2번입니다. 시각적으로 내 사진에 따르면 1000만 반복에 대해 xor128과 차이가 없습니다.

나는 당신의 사용 목적이 무엇인지 모르지만, 단지 놀라움이 있을 수 있다는 경고입니다.

 
Rorschach :

여기 , 나는 그것을 직접 사용하지 않았습니다.

고맙습니다! 코드는 OpenCL보다 큰 것으로 판명되었습니다. 어떻게든 알아내도록 노력하겠습니다.

 

ter.ver.의 친숙한 popados, 정수의 마법, 반올림, 모듈식 산술 및 트릭 더블 :-)

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 / 무작위성에 대한 시각적 "테스트"의 경우 무딘 정사각형 모듈로 외에도 "Ulam snail"의 변형이 사용됩니다.

 
Rorschach :

여기 , 나는 그것을 직접 사용하지 않았습니다.

이 코드에서 CRandomMersenne 및 CRandomMother의 성능을 측정했습니다. xor128보다 3배 느립니다. 이것은 그다지 유쾌하지 않습니다. 그러나 RNG를 끊은 코드에 따르면 xor128(세로 막대 없음)보다 좋아 보입니다.