MathRand() nasıl değerler üretir? - sayfa 2

 
yu-sha :

Lütfen bana MathRand()'ın değerleri nasıl aldığını söyleyin.

MathRand()'ın belirtilen aralıkta eşit olarak dağıtılması beklenebilir mi?

işte bir örnek, elbette başka, daha karmaşık algoritmalar da var ...

rand.c kaynağı:

 /***
*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 işlevi, Int sayısının 0'dan herhangi bir değere üretilmesi için gerekliydi.

Int'nin maksimum değeri = 2 147 483 647 olduğu için ona kadar hesaplıyoruz

Böyle bir fonksiyon var. Bence dağılım eşit .

 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);
}
 
Makalenin 4294967295'e kadar bir jeneratörü var
 
Rorschach :
Makalenin 4294967295'e kadar bir jeneratörü var

SB Alglib, yüksek hassasiyetli bir jeneratöre sahiptir

UPD: Bununla uğraşmaya çalıştım https://www.mql5.com/ru/forum/324066#comment_13500222 , işe yarıyor gibi görünüyor, ancak MQL5'te Alglib ile ilgili herhangi bir belge yok, Alglib web sitesini okumanız gerekiyor

 
Rorschach :
Makalenin 4294967295'e kadar bir jeneratörü var

Teşekkürler, hesaplamaların hızını karşılaştırdım.
Standart Rand() üzerindeki işlevim 2 kat daha yavaş çıktı. Kod çok daha basit gibi görünse de ...


 
Igor Makanu :

SB Alglib, yüksek hassasiyetli bir jeneratöre sahiptir

UPD: Bununla uğraşmaya çalıştım https://www.mql5.com/ru/forum/324066#comment_13500222 , işe yarıyor gibi görünüyor, ancak MQL5'te Alglib ile ilgili herhangi bir belge yok, Alglib web sitesini okumanız gerekiyor

Evet gördüm ama alglibsiz istiyorum. Ayrıca, bu fonksiyon kütle */% içerir. Hızı karşılaştırmadım, açıkçası daha yavaş. Makaledeki oluşturucu, bit düzeyinde ofsetlerle çalışır - hızlıdır.

 

Hızı optimize etmek için f-th'imi yeniden yazdım:

 int RandomInteger( int max_vl){ return ( int ) MathFloor (( MathRand ()+ MathRand ()* 32767.0 )/ 1073741824.0 *max_vl);} //случайное Int от 0 до  Max Int
Dağılım eşit çıktı. https://www.mql5.com/en/blogs/post/735953 blogunda deneyin resimlerine bakın

Makaleden RNG'yi yeniden yazdı.
Fazlalığı attı, işte olanlar:

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

Dağılım da tekdüzedir.

Her iki işlevin de hız karşılaştırmasını yaptım, makaledeki orijinali ve yalnızca MathRand():


Orijinal makale Rnd.Rand_01() - 602ms
rnu.Rand_01() makalesi ile kısaltılmıştır - 596 ms
Optimize edilmiş RandomInteger() sürümüm 840ms (eski sürüm 1200ms, yani %25 hızlandırılmış)
Basitçe MathRand() ile - 353 ms (en hızlı, ancak dağılım eşit olmayacak. Gerekli sayıların aralığı 32767'den fazlaysa, sonuç boşluklarla olacaktır. 32767'den küçükse, örneğin i=31111 , sonra bazı noktalara yuvarlama daha sık gerçekleşir.)

eğlence)
Rand 0 ... Max Int с равномерным распределением
Rand 0 ... Max Int с равномерным распределением
  • www.mql5.com
Потребовалась функция ГСЧ с гнерацией числа Int от 0 до любого значения.Получилась такая функция. Думаю распределение получилось равномерным. int RandomInteger(int max_vl){return
 
elibrarius :
İlginç. Standart kitaplıkta başka bir rastgele bulundu, ancak daha iyi olması pek mümkün değil.
 

neden işleri bu kadar karmaşık hale getiriyorsun?

bunu şöyle yapabilirsiniz (kabaca konuşursak):

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

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

Ve etrafta oynamak veya ne gösterdiğini görmek istiyorsanız, şöyle yapın:

 int x= 1 ;

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

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

Comment (x);

ve değerleri nasıl değiştirdiğini görün.

 
elibrarius :

Hızı optimize etmek için f-th'imi yeniden yazdım:

Dağılım eşit çıktı. https://www.mql5.com/en/blogs/post/735953 blogunda deneyin resimlerine bakın

Makaleden RNG'yi yeniden yazdı.
Fazlalığı attı, işte olanlar:

Dağılım da tekdüzedir.

Referanstan gelen dağılımla karşılaştırıldığında, farkı görmüyorum

Dosyalar: