RandomInt()

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

RandomInt()

Beitrag von AUGE_OHR »

hi,

ich verwende RandomInt() aber bin nicht damit zufrieden.

mit dieser Code erreiche so um die 60-65% ... geht da nicht mehr ?

Code: Alles auswählen

Procedure Main
LOCAL i
LOCAL iMax := 1000
LOCAL nZahl
LOCAL nPosi
LOCAL aTreff := {}

   SET ALTER TO _LOGFILE.TXT
   SET ALTER ON

   FOR i := 1 TO iMax
      nZahl := RandomInt(1,iMax)
      nPosi := ASCAN(aTreff,{|x| x[1] = nZahl } )
      IF nPosi > 0
         aTreff[nPosi,2] := aTreff[nPosi,2] +1
      ELSE
         AADD(aTreff,{nZahl,1} )
      ENDIF
   NEXT

   ? iMax := LEN(aTreff)
   ? "********"
   aTreff := ASort(aTreff,,, {|aX,aY| aX[2] < aY[2]} )
   FOR i := 1 TO iMax
       ? aTreff[i,1],aTreff[i,2]
   NEXT

   SET ALTER OFF
   SET ALTER TO

RETURN
gruss by OHR
Jimmy
Sören
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 205
Registriert: Mo, 07. Aug 2006 10:18
Wohnort: Leipzig
Danksagung erhalten: 11 Mal

Re: RandomInt()

Beitrag von Sören »

Hallo Jimmy,

da ich mit der Funktion RandomIn() hinsichtlich der Doppelungen auch nicht sehr zufrieden war,
verwende ich eine eigene Klasse zur Generierung von Zufallszahlen, bei der man einen Faktor
festlegen kann, der Doppelungen begrenzt.

Code: Alles auswählen

#include "common.ch"

Procedure Main

  LOCAL i
  LOCAL iMax := 1000
  LOCAL nZahl
  LOCAL nPosi
  LOCAL aTreff := {}
  LOCAL oRandom

  SET ALTER TO _LOGFILE.TXT
  SET ALTER ON

  oRandom := xRandom():New( iMax, 900 )  // innerhalb der ersten 900 generierten Zufallszahlen keine Doppelungen zulassen

  FOR i := 1 TO iMax
    nZahl := oRandom:NextValue()
    nPosi := ASCAN(aTreff,{|x| x[1] = nZahl } )
    IF nPosi > 0
      aTreff[nPosi,2] := aTreff[nPosi,2] +1
    ELSE
      AADD(aTreff,{nZahl,1} )
    ENDIF
  NEXT

  ? iMax := LEN(aTreff)
  ? "********"
  aTreff := ASort(aTreff,,, {|aX,aY| aX[2] < aY[2]} )
  FOR i := 1 TO iMax
    ? aTreff[i,1],aTreff[i,2]
  NEXT

  SET ALTER OFF
  SET ALTER TO

RETURN


//////////////////////////////////////////////////////////////////////////////////////////////////
// xRandom-Klasse
//
// - Klasse zur Generierung von Zufallszahlen
// - xLimit: (default: 100); entweder eine pos. Ganzzahl zw. 1..n (0 als Zufallszahl ist aus-
//   geschlossen) oder ein Array mit Min- und Max-Angabe (0 und negative Zahlen sind mgl.);
//   Bsp. f. xLimit: { 0, 70 }; { -10, 10 }; { 500, 1000 }
// - nDoubleLimit: Erzeugung doppelter Zufallszahlen bis zur Hoehe von nDoubleLimit verhindern
//   (default: 0 = Doppelungen zulassen); wenn nDoubleLimit = 100, wird innherhalb der ersten
//   100 Zufallszahlen keine Doppelung zugelassen, von 101. bis 200. Zufallszahl wird wieder
//   keine Doppelung zugelassen und von 201. bis 300. keine Doppelung usw.
//
// - Bsp.: oRandom := xRandom():New( 500, 100 )  // Zufallszahlen zw. 1 u. 500 erzeugen;
//                                               // aller 100 Zufallszahlen darf es keine Doppelung geben
//         nValue  := oRandom:NextValue()  // Zufallszahl erzeugen
//
/////////////////////////////////////////////////////////////////////////////////////////////////

CLASS xRandom
  PROTECTED:
    VAR nRandom
    VAR nShiftValue
  EXPORTED:
    VAR Value, Values
    VAR Limit
    VAR DoubleLimit
    METHOD Init, NextValue
ENDCLASS

METHOD xRandom:Init( xLimit, nDoubleLimit )

  DEFAULT xLimit       TO 100  // Limit standardmaessig auf 100 setzen
  DEFAULT nDoubleLimit TO 0    // Doppelungen per default zulassen

  ::DoubleLimit := nDoubleLimit

  if Valtype( xLimit ) == "A"  // xLimit ist ein Array mit Von-Bis-Wertepaar
    ::Limit := ( xLimit[2] - xLimit[1] + 1 )  // Limit zw. 1..n aus den Von-Bis-Werten errechnen
    ::nShiftValue := ( xLimit[1] - 1 )  // um wie viel muss das Ergebnis bei der Ausgabe verschoben werden
  ELSE  // xLimit ist eine pos. Ganzzahl zw. 1..n
    ::Limit := xLimit
    ::nShiftValue := 0
  endif

  // wenn ::DoubleLimit groesser als 95% von ::Limit ist, wird ::DoubleLimit auf 95% des ::Limit
  // herabgesetzt, da es andernfalls zu Stack Overflow Errors kommen kann
  if ( ::DoubleLimit * 100 / ::Limit ) > 95
    ::DoubleLimit := ( ::Limit * 95 / 100 )
  endif

  ::Values := {}

  // Ausgangswert
  ::nRandom := Seconds()
  ::nRandom := ( ::nRandom - Int( ::nRandom ) )

RETURN Self

METHOD xRandom:NextValue( lShiftValue )

  DEFAULT lShiftValue TO .T.

  ::nRandom := Log( ::nRandom + Sqrt( 2 ) ) * Exp( 3 )
  ::nRandom := Val( Str( ::nRandom - Int( ::nRandom ), 17, 15 ) )

  ::Value := Int( ::Limit * ::nRandom ) + 1  // +1 <-- keine 0 zulassen

  if ::DoubleLimit > 0

    if Len( ::Values ) == ::DoubleLimit
      ::Values := {}
    endif

    if AScan( ::Values, ::Value ) > 0
      ::Value := ::NextValue( .F. )  // bei rekursivem Aufruf kein Verschieben des Wertebereiches zulassen (.F.)
    ELSE
      AAdd( ::Values, ::Value )
    endif

  endif

  ::Value += iif( lShiftValue, ::nShiftValue, 0 )

RETURN ::Value
Beste Grüße,
Sören
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: RandomInt()

Beitrag von AUGE_OHR »

hi,
Danke für deine Antwort.
Sören hat geschrieben:

Code: Alles auswählen

#include "common.ch"
...
  ::nRandom := Log( ::nRandom + Sqrt( 2 ) ) * Exp( 3 )
  ::nRandom := Val( Str( ::nRandom - Int( ::nRandom ), 17, 15 ) )
die beiden Zeilen kommen mir bekannt vor ...
// BaseRandom Function is example Random Function from Alaska, but
// it has a decided tendancy to avoid numbers near the edge of the range!
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: RandomInt()

Beitrag von AUGE_OHR »

ich hab mal weiter gesucht und das gefunden.
re : Random()
public.xbase++.clipper-migration
11. August 2005

sowie

Mersenne Twister PRNG
public.xbase++.clipper-migration
12. August 2005
die Lösungen die mittels MT erzeugt werden haben deutlich weniger Dubletten als die beiden Alaska Lösungen.

Randomint -> 605 / 1000
T. Braun -> 50 / 1000

Code: Alles auswählen

   FOR i := 1 TO iMax
      nZahl := RandomInt(1,iMax)
*      nZahl := my_random_generator(  oTw , 1 , iMax ) 

      nPosi := ASCAN(aTreff,{|x| x[1] = nZahl } )
      IF nPosi > 0
         aTreff[nPosi,2] := aTreff[nPosi,2] +1
      ELSE
         AADD(aTreff,{nZahl,1} )
      ENDIF
   NEXT
   ? "**********"  
   ? iMax := LEN(aTreff)
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: RandomInt()

Beitrag von AUGE_OHR »

Nachtrag : man sollte sich dann auch mal die "Häufigkeit" der Dubletten ansehen ...

Code: Alles auswählen

   aTreff := ASort(aTreff,,, {|aX,aY| aX[2] < aY[2]} )
   FOR i := 1 TO iMax
       ? aTreff[i,1],aTreff[i,2]
   NEXT
und dann kommt man auch darauf warum sich so grosse Unterschiede ergeben.
tatsächlich liefert mir der "Mersenne Twister pseudorandom number generator" zwar weniger Treffer aber wenn dann auch viel öfter :banghead:

also ohne zusätzliche Prüfung, wie Sören es seiner Class hat, bekommt man keine guten Random Nummern.
gruss by OHR
Jimmy
Antworten