Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Lineares RandomRange für Real (https://www.delphipraxis.net/88256-lineares-randomrange-fuer-real.html)

Alexander Roth 12. Mär 2007 17:12


Lineares RandomRange für Real
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

also ich habe mir gedacht, wieso immer nur das ganz zufällige RandomRange, wo die Zahlen so völlig gleichverteilt sind.
Eine Lineare Zahlenverteilung wäre doch schön.
Also so was wäre toll
Zitat:

0 0
1 100
2 200
3 300
4 400
5 500
6 600
7 700
8 800
9 900
10 1000
Also habe ich mich daran gemacht:

Der Code:

Erstmal für Real Zufallszahlen
Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Description:
  Procedure:   RandomRRange
  Arguments:   min,max:real; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true
  Result:      real
  Detailed description:
-----------------------------------------------------------------------------}
function RandomRRange(min,max:real; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true):real;
begin
  min:=min*power(10,nachkomma);
  max:=max*power(10,nachkomma);
  if IncludeMin then
    min:=min-1;
  if IncludeMax then
    max:=max+1;

  result:=randomrange(round(min),round(max))/power(10,nachkomma);
end;
Dann das besondere
Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Description:
  Procedure:   RandomRRange
  Arguments:   min,max:real; IncreaseProbability, DecreaseProbability:boolean; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true
  Result:      real
  Detailed description: Falls IncreaseProbability dann kommen die größeren Zahlen linear häufiger vor als die kleineren
                         Falls DecreaseProbability dann kommen die kleineren Zahlen linear häufiger vor als die größeren
                         Falls beide, dann kommen die mittlere Zahlen linear häufiger vor als die größeren und kleineren
-----------------------------------------------------------------------------}
function RandomRRange(min,max:real; IncreaseProbability, DecreaseProbability:boolean; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true):real;
begin
  result:=RandomRRange(min,max,nachkomma,IncludeMin, IncludeMax);

  if IncreaseProbability and not DecreaseProbability then
    result:=RandomRRange(min+RandomRRange(0,max-min,nachkomma),max,nachkomma,IncludeMin, IncludeMax);

  if not IncreaseProbability and DecreaseProbability then
    result:=RandomRRange(min,max-RandomRRange(0,max-min,nachkomma),nachkomma,IncludeMin, IncludeMax);


  if IncreaseProbability and DecreaseProbability then
    if randombool then
      result:=RandomRRange(min,max/2,true,false,nachkomma) //links
    else
      result:=RandomRRange(min+(max-min)/2,max,false,true,nachkomma);   //rechts
end;
Dann die Test Routine
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
    i:integer;
    zufall:real;

    ar: array[0..10] of integer;
begin
  randomize;
  FillChar(ar,sizeof(ar),0);


  for i:=0 to 1100000 do
    begin
    zufall:=RandomRRange(0,10,true,true);
    inc(ar[trunc(zufall)]); //  WICHTIG, das hier trunc steht!!!!! das macht nämlich klar wieso 10 nur ganz selten vorkommt
    end;

  s:='';
  for i:=0 to length(ar)-1 do
    s:=s+inttostr(i)+' '+inttostr(ar[i])+#13+#10;

  intxtschreiben(s);
  Close;
end;
Und dann natürlich noch intxtschreiben
Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Description: Schreibt in eine TXT rein
  Procedure:   intxtschreiben
  Arguments:   text:string; pfad:string=''; vorherloschen:boolean=true
  Result:      None
  Detailed description:
-----------------------------------------------------------------------------}
procedure intxtschreiben(text:string; pfad:string=''; const endung:string='.txt'; vorherloschen:boolean=true);
var txt:textfile;
begin
  if pfad='' then
//    pfad:=ExtractFilePath(Application.ExeName)+dateToStr(now)+' '+inttostr(hourof(now))+' Uhr und '+inttostr(minuteof(now))+' Minuten'+endung
    pfad:=ExtractFilePath(Application.ExeName)+dateToStr(now)+' '+inttostr(hourof(now))+'h '+inttostr(minuteof(now))+'m '+inttostr(secondof(now))+'s '+endung
  else
    DelDubbleExtension(pfad,endung);

  try
    assignfile(txt,pfad);
    if (fileexists(pfad))and(not vorherloschen) then append(txt) else rewrite(txt);
    writeln(txt,text);
    closefile(txt);
  except
    showmessage('Fehler beim schreiben');
  end;
end;

So ich habe mir die Zufallsverteilung mal angeschaut in Excel und es erfüllt auch den groben Verlauf, aber leider steigt der Verlauf der Verteilung fast e Funktionsmäßig an.
Also nicht linear.
Ach ja dazu gleich mal die Daten für steigend, sinkend, beides (auch im Anhang)
Zitat:

0 56799
1 179147
2 316328
3 475035
4 660863
5 880353
6 1159318
7 1531780
8 2107263
9 3632972
10 143
Zitat:

0 3632360
1 2107747
2 1531753
3 1158711
4 880333
5 660495
6 475303
7 317350
8 179262
9 56687
10 0
Zitat:

0 117919
1 396274
2 770052
3 1345257
4 2869959
5 2871358
6 1345788
7 769382
8 395701
9 118311
10 0
Wisst ihr woran das liegen könnte?

Gruß Alexander

PS: Ich hoffe ihr seid nicht in der Datenflut ertrunken. :roteyes:

yörsch 13. Mär 2007 07:18

Re: Lineares RandomRange für Real
 
Moin Moin
es dürfte an dem ROUND liegen, genau erklären kann isch´s aber auch nicht!
liegt wohl am abrunden!
Versuch mal was anderes... trunc, ....

Alexander Roth 13. Mär 2007 07:34

Re: Lineares RandomRange für Real
 
Am Round im RandomRRange für Real Zahlen? Also das
Zitat:

Zitat von Alexander Roth
Erstmal für Real Zufallszahlen
Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Description:
  Procedure:   RandomRRange
  Arguments:   min,max:real; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true
  Result:      real
  Detailed description:
-----------------------------------------------------------------------------}
function RandomRRange(min,max:real; nachkomma:integer=5; IncludeMin:boolean=true; IncludeMax:boolean=true):real;
begin
  min:=min*power(10,nachkomma);
  max:=max*power(10,nachkomma);
  if IncludeMin then
    min:=min-1;
  if IncludeMax then
    max:=max+1;

  result:=randomrange(round(min),round(max))/power(10,nachkomma);
end;

Aber wenn ich das aufrufe gibt es eine gleichmäßige Zufallsverteilung.

Gruß Alexander

sirius 13. Mär 2007 07:35

Re: Lineares RandomRange für Real
 
Ich sehe zwar, was du machst, aber ich kanns mathematisch nicht fassen.

Vielleicht ein anderer Ansatz:
Du willst also eine Dichtefunktion, welche linear von min bis max ansteigt (oder abfällt). Das würde bedeuten du brauchst eine quadratische Verteilungsfunktion (Integral der Dichtefunktion). Jetzt musst dur dir also eine quadratische Funktion vorstellen in dem Bereich von x=[min;max] und y=[0;1]. Dabei geht dir Funktion durch die zwei Punkte P1=(min;0) und P2=(max;1). Diese Funktion musst du dir erstmal auf dem Papier erstellen.
Und im Prinzip ziehst du jetzt gleichverteilt (also das, was Delphi mit allen random-Funktionen macht) einen y-wert und rechnest auf den x wert zurück. Dann dürftest du eine lineare Dichetfunktion erreichen. um von y auf x zu kommen müsstest du also dann deine quadratische Funktion invertieren (da dürfte also eine Wurzel reinkommen).

Alexander Roth 13. Mär 2007 07:42

Re: Lineares RandomRange für Real
 
Ich verstehe. Ich probiere es aus.
Danke

Gruß Alexander

Alexander Roth 13. Mär 2007 08:01

Re: Lineares RandomRange für Real
 
Jaaa.... also deine Methode glaube ich habe dich doch nicht so ganz verstanden, bzw sie funktioniert nicht so ganz: Weil:
wenn, min=0; max:=1;
dann kann man quadrieren und muss danach NICHT verschieben und kann wieder die wurzel ziehen und es bleibt das selbe.

Deshalb habe ich einfach ein bisschen rumprobiert und so unverständlich es für mich ist, das:
Delphi-Quellcode:
  result:=sqrt(random)*(max-min)+min;
funktioniert einwandfrei.
Ich weis nicht wieso.

Quadrieren bringt den linken Ast der Quadratischen Funktion. Das verstehe ich. Quadrat heißt viele Kleine, D.h. bei 0,1,.. sind sehr viele, d.h. linker Ast einer Quadratischen Funktion.

Doch wieso das mit der Wurzel klappt?

Gruß Alexander

sirius 13. Mär 2007 09:27

Re: Lineares RandomRange für Real
 
So funktioniert es natürlich. Vielleicht nochmal als Info, wie die Mathematik dahinter ist:
Als Beispiel für Delphi:
Delphi-Quellcode:
type TLinVerteilung=class
       constructor create(min,max:double);
       function getvalue:double;
      private
       a,b,c:double;
end;

unction TLinVerteilung.getvalue:double;
var y:double;
begin
  y:=random; //y-wert
  //quadratische funktion umkehren um aus dem y-Wert den x-Wert zu bestimmen
  //(nur positive "Lösung")
  //x=-b/(2a) + sqrt( b^2/(4a^2) - (c-y)/a )
  result:=-b/(a*2)+sqrt(sqr(b/a)/4-(c-y)/a); //x-->result
end;
constructor TLinVerteilung.create(min,max:double);
begin
  inherited create;
  //Parameter der quadratischen Funktion für eine lineare Verteilung berechnen
  //y=a*x^2 + b*x + c
  //P1=(min,0)
  //P2=(max,1)
  //P1 ist gleichzeitig Scheitelpunkt der quadratischen Funktion
  a:=1/sqr(max-min);
  b:=-2*min*a;
  c:=sqr(min)*a;
end;
Und wenn du jetzt die Variablen a,b,c oben bei getvalue einsetzt, kommst du genau auf deine Gleichung.
(Hey, das ist eine mathematische Herleitung mit Delphi :mrgreen: )

Ansonsten ist es schwer zu erklären. du musst dich in Verteilungsfunktionen einarbeiten.

Alexander Roth 13. Mär 2007 12:55

Re: Lineares RandomRange für Real
 
:gruebel: Da ist das einfache wurzelziehen aber einfacher.

Wieso beim Quadrieren, aber ein linke Parabelast und beim wurzelziehen was lineares rauskommt, ist mir aber jetzt noch nicht klar.

Es müsste doch analog zu Quadrieren der rechte Parabelast rauskommen.

Wieso ist dem nicht so?

Gruß Alexander

sirius 13. Mär 2007 13:36

Re: Lineares RandomRange für Real
 
Natürlich ist deins einfacher.
Ist auch exakt dasselbe, nur gekürzt. Das sollte ja nur mal vor Auge führen, was mathematisch dahinter steht (vielleicht willst du ja mal was anders als eine lineare Verteilung)

Wenn du eine Zufallszahl aus einer bestimmten Dichtefunktion haben willst (die bei dir eine lineare Funktion darstellt), dann bildet man erst die Verteilungsfunktion indem man die Dichtefunktion integriert (würde also aus der linearen Funktion eine quadratische Funktion machen), und dann muss man nur eine zufällige Zahl zwischen 0 und 1 ziehen und bestimmt in der Verteilungsfunktion dazu den x-Wert (eine Verteilungsfunktion hat immer den Wertebereich [0;1] oder besser [0%;100%]). Das ist alles. Mathematisch geht das indem du aus der quadratischen Funktion, die Umkehrfunktion also eine Wurzelfunktion bildest.


(Der andere Parabelast kommt heruas, wenn du (meine Lösung durchgehend) die zweite ösung einer quadratischen Gleichung nimmst, also letzenendes ein Minus vor das "sqrt" setzen. Das ist rein mathematisch zwar richtig, aber für die reale Lösung völlig irrelevant.)


Edit und PPS: Du solltest dir mal ein paar mehr stochastische Grundkenntnisse aneignen. Ist ganz sinnvoll wenn man etwas stochastisches programmiert :zwinker:

Edit2: Hab in der Erklärung noch einen Nebensatz ergänzt.

Alexander Roth 13. Mär 2007 13:59

Re: Lineares RandomRange für Real
 
Zitat:

Zitat von sirius
Natürlich ist deins einfacher.
Ist auch exakt dasselbe, nur gekürzt. Das sollte ja nur mal vor Auge führen, was mathematisch dahinter steht (vielleicht willst du ja mal was anders als eine lineare Verteilung)

Wenn du eine Zufallszahl aus einer bestimmten Dichtefunktion haben willst (die bei dir eine lineare Funktion darstellt), dann bildet man erst die Verteilungsfunktion indem man die Dichtefunktion integriert (würde also aus der linearen Funktion eine quadratische Funktion machen), und dann muss man nur eine zufällige Zahl zwischen 0 und 1 ziehen und bestimmt in der Verteilungsfunktion dazu den x-Wert. Das ist alles. Mathematisch geht das indem du aus der quadratischen Funktion, die Umkehrfunktion also eine Wurzelfunktion bildest.

Jetzt habe ich es kapiert. Danke für die Erklärung.
Zitat:

Zitat von sirius
Edit und PPS: Du solltest dir mal ein paar mehr stochastische Grundkenntnisse aneignen. Ist ganz sinnvoll wenn man etwas stochastisches programmiert :zwinker:

Tja, noch war Stochastik nicht dran. Kommt erst in ein paar Monaten.

Gruß Alexander :hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:23 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz