Wie erzeugt MathRand() Werte? - Seite 3

 

Ich habeMathRandomUniform zu meinem Skript zum Vergleich hinzugefügt.
Ich habe die Punktgenerierung auf 1000000 gesetzt. Um die Verteilung zu schätzen, stelle ich alle 1000000 Punkte auf dem Bildschirm als 1000*1000 Quadrat dar. Je öfter Sie einen Punkt treffen, desto heller ist seine Farbe.

Ich habe 10 Millionen RNG-Wiederholungen eingestellt, so dass im Durchschnitt jeder Punkt 10 Mal getroffen werden sollte.

Hier sind die Ergebnisse:
RND:


Meine Variante von RandomInteger:


Auf MathRand():


Unter MathRandomUniform():


Die ersten beiden RNDs sind recht gleichmäßig, 3 und 4 haben Lücken, d. h. sie sind nicht gleichmäßig.
Die Sprünge sind auf die MathRand-Auflösung = 32767 zurückzuführen. Bei einem Multiplikator von 1000000 werden 1000000/32767=30 Punkte übersprungen. MathRandomUniform ist vom Bild her ähnlich, wahrscheinlich hat es die gleichen 30 Auslassungen.

Eine andere Variante. Setzen wir die Höchstzahl auf 30000.
RND und RandomInteger sind gleich, als ob sie eine Million wären .MathRand und MathRandomUniform sieht wie folgt aus (mit vergrößertem Teilstück):


Es gibt keine Lücken (schwarze Punkte bis zur Position 30000). Einige sind jedoch deutlich heller. Dies ist eine ungerade Rundung von 30000/32767. Jeder 11. Punkt erhält doppelt so viele Treffer.

Etwas Gleichmäßiges erhält man von MathRand bei maximal 3000... 4000. Hier ist eine vergrößerte Variante für 3500:


Die ersten beiden Variantenwerdenbei Annäherung an die maximale Zahl von 100 Millionen für RandomInteger (die eine Auflösung von etwa 1 Milliardehat ) und 400 Millionen bei einer Auflösung von 4 Milliarden für RND, - aufgrund der Rundung ebenfalls anfangen, sich ungleichmäßig zu verteilen.

Ich habe die Datei beigefügt, Sie können das Experiment wiederholen.
Ich habe beschlossen, meine eigene Funktion für mich selbst zu verwenden, sie ist 25% langsamer als RND, aber kompakter und übersichtlicher, ich kann die Auflösung bis zu 32767 Mal mehr erhöhen, siehe Code im Blog.


Anmerkung:
Der RND-Entwickler aus dem Artikel wies darauf hin, dass

Bei seed=0 ändert die Funktion die Anfangswerte zufällig.

Bei jedem Neustart setze ich seed=0, aber das Bild mit den Verteilungen ändert sich bei Neustarts nicht. D.h. die Aussage ist falsch. Aus dem Code ist auch nicht ersichtlich, warum es zufällig werden sollte. Um also zufällig zu initialisieren, muss seed auf eine Zufallszahl gesetzt werden, zum Beispiel seed=GetTickCount();

Bei der Funktion RandomInteger() sehen wir eine Umverteilung der Punkte bei Neustarts. Wenn srand(0); gesetzt ist, beginnt die Verteilung auch bei Neustarts zu wiederholen. So für diese Funktion zufällig zu initialisieren, muss ich entweder nicht srand aufrufen, oder MathSrand(GetTickCount()) mit Zeitstempel zu verwenden.

Dateien:
 

Denken Sie daran, dass xor128 spezielle Zufälligkeitstests durchläuft und mit standard rand

Forum für Handel, automatisierte Handelssysteme und Strategietests

Maschinelles Lernen im Handel: Theorie, Praxis, Handel und mehr

Rorschach, 2020.04.19 22:18

Ich bin ein Handwerker, ich habe die RSCH kaputt gemacht(((

#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 Möglichkeit: w muss eine Potenz von 2 sein, k ist ein Vielfaches von 4

Weg 2: srand auskommentieren

Methode 2 sollte auch bei dem Mersen-Wirbel funktionieren

 
Rorschach:

Beachten Sie, dass xor128 spezielle Zufälligkeitstests besteht und mit einem Standard-Rand kann es



Sie zeigen jeden 16. Randaufruf an. Aus dieser Periodizität ergibt sich eine Art Muster.
Ich verwende alle aufeinanderfolgenden Anrufe zu je 2 Stück. Optisch sehe ich auf meinen Bildern keinen Unterschied zu xor128 bei 10 Millionen Wiederholungen.
 
Rorschach:

Beachten Sie, dass xor128 spezielle Zufälligkeitstests besteht und mit einem Standard-Rand kann es


Ich habe versucht, meine eigene Funktion und xor128 in Ihrer Funktion zu ersetzen

#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() hat auch einige Unterteilungen.
Besser mit xor128, aber es gibt ein gewisses Banding:

Ich bin mir nicht sicher, ob diese Bindestriche von RandomInteger() im normalen Gebrauch (nicht 1 aus 16) irgendeine Wirkung haben... Und es ist nicht klar, was sie meinen...

Ich denke aber, dass xor128 sicherer ist.

 
Rorschach:

Beachten Sie, dass xor128 spezielle Zufälligkeitstests besteht und mit einem Standard-Rand kann es


Haben Sie den Code von Mersen? Ich hatte es irgendwo auf OpenCL, bin aber noch nicht dazu gekommen, es auf MQL5 zu portieren. Es wäre interessant zu vergleichen.

Methode 2 sollte auch bei Mersens Wirbel funktionieren


 
Rashid Umarov:

Haben Sie den Code von Mersen? Ich hatte es irgendwo auf OpenCL, bin aber noch nicht dazu gekommen, es auf MQL5 zu portieren. Es wäre interessant zu vergleichen.

Hier habe ich es selbst nicht benutzt.

 
elibrarius:

Sie zeigen jeden 16. Anrufrand an. Aus dieser Periodizität ergibt sich eine Art Muster.
Ich verwende alle aufeinanderfolgenden Anrufe zu je 2 Stück. Optisch sehe ich auf meinen Bildern keinen Unterschied zu xor128 bei 10 Millionen Wiederholungen.

Ich weiß nicht, was Sie damit bezwecken, aber ich möchte Sie warnen, dass es Überraschungen geben kann.

 
Rorschach:

Hier habe ich es selbst nicht benutzt.

Danke, der Code war größer als bei OpenCL. Ich werde versuchen, es irgendwann herauszufinden.

 

ein freundlicher Treffer auf ter.ver, die Magie der ganzen Zahlen, Rundung, modulare Arithmetik und die Tricks der Verdopplung :-)

Wenn f(x) :: ganzzahlig gleichmäßig auf (0;N] verteilt ist, bedeutet dies nicht, dass g(x)=N/(double)f(x) gleichmäßig auf (0;1] verteilt ist und auch alle Tests besteht.

Das Gleiche gilt für g(x) = f(x) mod M , mit der seltenen Ausnahme N mod M = 0.

PS/ und g(x)=f(x)/(double)N sind übrigens auch nicht einheitlich. Es wird Brennpunkte der Spaltung geben. Das bedeutet, dass die Diagramme Moiré zeigen werden.

PPS/ für einen visuellen "Test" der Zufälligkeit werden neben dem stumpfen Modulo-Quadrat auch Variationen der "Ulam-Schnecke" verwendet

 
Rorschach:

Hier habe ich es selbst nicht benutzt.

Messung der Leistung von CRandomMersenne und CRandomMother anhand dieses Codes. Sie sind 3 Mal langsamer als xor128. Das ist nicht sehr befriedigend. Aber nach deinem Code, wo du den GSF gebrochen hast, sehen sie besser aus als xor128 (ohne den vertikalen Balken).