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

 
유샤 :

MathRand()가 값을 얻는 방법을 알려주세요.

MathRand()가 명시된 범위에 고르게 분포될 것으로 예상할 수 있습니까?

여기에 하나의 예가 있습니다. 물론 다른 더 복잡한 알고리즘이 있습니다 ...

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

0에서 임의의 값까지 Int 숫자를 생성하는 RNG 함수가 필요했습니다.

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 의 생성기가 있습니다.

SB Alglib에는 고정밀 제너레이터가 있습니다.

UPD: https://www.mql5.com/ru/forum/324066#comment_13500222 처리하려고 했는데 작동하는 것 같지만 MQL5의 Alglib에 대한 문서가 없습니다. Alglib 웹사이트를 읽어야 합니다.

 
Rorschach :
기사 에는 최대 4294967295 의 생성기가 있습니다.

덕분에 계산속도를 비교해봤습니다.
표준 rand()에 대한 내 기능은 2배 느린 것으로 나타났습니다. 코드가 훨씬 간단해 보이지만 ...


 
Igor Makanu :

SB Alglib에는 고정밀 제너레이터가 있습니다.

UPD: https://www.mql5.com/ru/forum/324066#comment_13500222 처리하려고 했는데 작동하는 것 같지만 MQL5의 Alglib에 대한 문서가 없습니다. Alglib 웹사이트를 읽어야 합니다.

예, 보았지만 aglib 없이 원합니다. 또한 해당 함수에는 질량 */%가 포함됩니다. 나는 속도를 비교하지 않았다, 분명히 더 느리다. 기사의 생성기는 비트 오프셋과 함께 작동합니다. 속도가 빠릅니다.

 

속도를 최적화하기 위해 내 f-th를 다시 작성했습니다.

 int RandomInteger( int max_vl){ return ( int ) MathFloor (( MathRand ()+ MathRand ()* 32767.0 )/ 1073741824.0 *max_vl);} //случайное Int от 0 до  Max Int
분포가 균일한 것으로 나타났습니다. 블로그 https://www.mql5.com/en/blogs/post/735953 에서 실험 이미지를 참조하십시오.

기사에서 RNG를 다시 작성했습니다.
초과분을 버리십시오. 일어난 일은 다음과 같습니다.

 //если из 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() - 602ms
기사 rnu.Rand_01()로 단축 - 596ms
RandomInteger()의 최적화된 버전은 840ms입니다(이전 버전은 1200ms, 즉 25% 빨라짐).
간단히 MathRand() - 353ms(가장 빠르지만 분포가 고르지 않습니다. 필요한 숫자의 범위가 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 :

속도를 최적화하기 위해 내 f-th를 다시 작성했습니다.

분포가 균일한 것으로 나타났습니다. 블로그 https://www.mql5.com/en/blogs/post/735953 에서 실험 이미지를 참조하십시오.

기사에서 RNG를 다시 작성했습니다.
초과분을 버리십시오. 일어난 일은 다음과 같습니다.

분포도 균일하다.

레퍼런스의 분포와 비교하면 차이를 못느끼겠음