Ankündigung

Einklappen
Keine Ankündigung bisher.

zufälligen Wert erzeugen (exponentielle Wahrscheinlichkeitsabnahme bei Entfernung von Mittelwert)

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • zufälligen Wert erzeugen (exponentielle Wahrscheinlichkeitsabnahme bei Entfernung von Mittelwert)

    Hi@all,
    Ich möchte einen Zufallswert erzeugen. Dabei soll der Wertebereich zwischen 1 und 1000 liegen.
    Das allein wäre an sich nicht das Problem, allerdings soll die Wahrscheinlichkeit - dass ein bestimmter Wert erzeugt wird - exponentiell abnehmen, je weiter er sich vom Mittelwert (500) entfernt.
    Irgendwie Fehlt mir der passende Ansatz für dieses Problem, daher hoffe ich, dass mir hier jemand von euch weiterhelfen kann.

    Hier mal noch eine kleine Grafik, um das ganze vielleicht etwas besser zu verdeutlichen.

  • #2
    OK, nach ein wenig Nachdenken habe ich eine - für mich passende - Lösung gefunden.
    Hier mal ein kleines dirty Codesnippet, falls es jemanden interessiert:

    PHP-Code:
    $x 0;
    $expSize 5;
    $minValue 1;
    $maxValue 1000;

    for (
    $i 0$i $expSize$i++) {
        
    $x += (int)round(rand($minValue$maxValue) / $expSize);
    }

    echo 
    $x
    Wie man sieht habe ich eigentlich nichts weiter gemacht, als den Durchschnitt mehrerer Zufallswerte zu errechnen, dadurch nährt sich der Gesamtwert dem Mittelwert an und die Wahrscheinlichkeit dass ein bestimmter Wert auftaucht wird geringer, je weiter dieser vom Mittelwert entfernt ist. Desweiteren kann man die stärke der exponentiellen Abnahme mit der Variable $expSize beeinflussen.

    Ich würde mich allerdings über Verbesserungsvorschläge sehr freuen. Mir gefällt z.B. noch nicht, dass ich dafür eine Schleife verwende, denn dann steigt mit der Variable $expSize auch die Ausführungszeit, desweiteren sollte man die steigung der exponentiellen Kurve nich etwas genauer einstellen können.

    Kommentar


    • #3
      Verschieb den Mittelpunkt auf 0, stell das Ding aufm Kopf und das y ist dein gesuchter Zufallswert. Um y zu bestimmen pickst du ein zufälliges x (und das machst du "linear" mit rand()).
      Achja, das ist eine Quatratische Funktion: y = x^2 (wobei in dem Fall eine ungrade Potzen sinnvoller ist, da passt auch gleich das Vorzeichen)
      Wenn du das noch multiplizierst, also a*x^3, dann kannst den "Wahrscheinlichkeitsabfallen" zu den Rändern abflachen. Wenn du um den 0 Punkt eine höhere Wahrscheinlichkeit haben willst kannst du die Potzen erhöhen.
      Das Kunststück dabei ist eigentlich nur die Funktion (die quatratische) so zu wählen, dass du das gewünschte Ergebnis bekommst. Eventuell ist es auch nötig a dynamisch zu berechnen. Da fehlt mir aber ein wenig die Muse genauer darüber Nachzudenken, dass müsste ich wahrscheinlich auch antesten. Schulmathe ist bei mir schon ein paar Tage her.

      Kommentar


      • #4
        Wenn ich mir deinen Ansatz #2 so anschaue sieht es ganz so aus, als wolltest du näherungsweise eine normalverteilte Zufallsvariable erzeugen.
        Der zentrale Grenzwertsatz besagt, dass sich unter bestimmten Voraussetzungen die Verteilung der Summe unabhängiger, identisch verteilter Zufallszahlen einer Normalverteilung nähert.
        Ist das der Fall?

        Kommentar


        • #5
          Ja genau sowas suche ich aber die Formeln die auf dem von dir verlinkten Wikipedia-Artikel stehen, sind dann doch eine Nummer zu hoch für mich. Gibts da vielleicht schon vorgefertigte funktionen?

          Kommentar


          • #6
            Fertige Funktionen dafür aus dem PHP-Kern sind mir nicht bekannt. Wenn du ein wenig im Netz suchst, findest du auch eine Menge Statistk-Klassen, vielleicht ist da was dabei.
            Der folgende Algorithmus nutzt die sog. Zwölferregel
            PHP-Code:
             /*
              * @return: normal/Gauß distributed random Value or false if error
              * @param average arithmetic mean
              * @param stdev standard deviation 
              */
              
            public static function stdRand($average 0$stdev 1)
              {
                if(
            $stdev 0) return false;
                
            $v 0;
                for(
            $i=0$i 12$i++){
                  
            $v += rand(0,10000);
                }
                
            $normRand $v/10000 6.0;
                return 
            $normRand $stdev $average;
              } 
            Ein Spezialfall ist die Zwölferregel, die sich auf die Summe von zwölf Zufallszahlen aus einer Gleichverteilung auf dem Intervall [0,1] beschränkt und bereits zu passablen Verteilungen führt.
            Ob jedoch die obige Funktion in Bezug auf Güte und Geschwindigkeit für deine Anwendung ausreicht, kann ich nicht beurteilen.

            Kommentar


            • #7
              Ok, also erstmal danke für deine Hilfe.
              Ich hatte am Wochenende mal wieder ein bisschen mehr Zeit und hab mal die Polar-Methode (da diese von Computern recht schnell ausgeführt wird) als PHP-Funktion umgesetzt vielleicht kann es ja jemand gebrauchen:
              PHP-Code:
              public static function polarMethod() {
                      do {
                          
              $u1 * (mt_rand() / mt_getrandmax()) - 1;
                          
              $u2 * (mt_rand() / mt_getrandmax()) - 1;

                          
              $q $u1 $u1 $u2 $u2;
                      } while (
              $q === || $q >= 1);

                      
              $p sqrt((-log($q))/$q);
                  
                  return [
              $u1 $p$u2 $p];

              Man könnte die Funktion evtl. noch dahingehend abändern, dass man ihr einige Parameter übergeben kann, welche dann in den Algo mit einfließen.

              P.S.: Kann mir irgendjemand sagen, was der höchste bzw. niedrigste wert ist, den mir dieser Algorithmus - so wie er jetzt ist - ausspucken kann?

              Kommentar


              • #8
                Die Normalverteilung kennt keinen höchsten bzw. niedrigsten Wert. Deine Funktion erzeugt ein Array mit 2 normalverteilten Zufallszahlen mit den Mittelwert µ = 0 und der Standardabweichung σ = 1.
                Mit diesen Werten liegen ca.
                68,3 % der Realisierungen im Intervall µ ± σ,
                95,4 % im Intervall µ ± 2σ und
                99,7 % im Intervall µ ± 3σ

                Mit einer sehr kleinen Wahrscheinlichkeit können auch Werte >5, >10 usw. generiert werden.

                Wenn du solche Funktionen nutzen möchtest, ist anzuraten, dich auch etwas mit den mathematischen Grundlagen zu beschäftigen.

                Das deine Funktion ein Array liefert finde ich wenig praktikabel. Alternativ (Liefert immer nur einen Wert):
                PHP-Code:
                class Statistic {

                  private static 
                $useValue;
                  private static 
                $useValueExists false;

                 
                /*
                  * generate random numbers folloeing normal/gaussian distribution
                  * @return: random number or false if error
                  * @param average arithmetic mean
                  * @param stdev standard deviation 
                  */
                  
                public static function gaussPolar($average 0$stdev 1)
                  {
                    if(
                $stdev 0) return false;
                    if(
                self::$useValueExists) {
                      
                self::$useValueExists false;
                      return 
                self::$useValue $stdev $average;
                    }
                    else {    
                      
                $rndmax = (float)getrandmax();
                      
                $w 2.0;
                      while((
                $w >= 1.0) || ($w == 0.0)) {
                        
                $x 2.0 * ((float)rand())/$rndmax 1.0;
                        
                $y 2.0 * ((float)rand())/$rndmax 1.0;
                        
                $w = ($x $x) + ($y $y);
                      }
                      
                $w sqrt((-2.0 log($w)) / $w) ;
                      
                self::$useValue $y $w ;
                      
                self::$useValueExists true ;
                      return 
                $x $w $stdev $average;
                    }
                  }


                LG jspit


                Kommentar

                Lädt...
                X