AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)
Thema durchsuchen
Ansicht
Themen-Optionen

Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

Ein Thema von Bambuti2000 · begonnen am 18. Jun 2014 · letzter Beitrag vom 18. Jun 2014
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Bambuti2000
Bambuti2000

Registriert seit: 11. Okt 2007
Ort: Troisdorf
44 Beiträge
 
Delphi XE2 Architect
 
#1

Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:08
Hallo Communnity,

ich hab mal wieder ein Problem.
Wir haben vor die Gewinner einer Verlosung per Zufallsgenerator zu ermitteln. (Haha, kein Problem)
Jetzt soll aber eine Gewichtung mit einfließen. Und zwar soll sich für jeden Euro(€) Einzahlung auf's Konto die Gewinnchance um 1 erhöhen.
Damit es nicht so einfach ist, mal ein paar Randdaten:
- ca. 150000 Kunden
- Einlagen zwischen 1€ & 1000000€

Hier mal mein Code der zwar funktioniert, aber nur wenn ich die Summen um den Faktor 100 dividiere.
Delphi-Quellcode:
      Randomize;
      srcFile := TStringStream.Create;
      srcStrings := TStringList.Create;
      randList := TStringList.Create;

      try
        WriteLn('Lade Quelle ...');
        srcFile.LoadFromFile('source.csv');
        srcStrings.LoadFromStream(srcFile);
        WriteLn('Erstelle Zufallsliste nach Gewichtung ...');
        for I := 0 to srcStrings.Count - 1 do
        begin
          Write(#13, Format('[%d%%]', [(100 * I) div srcStrings.Count]));
          for J := 1 to srcStrings.Count - 1 do
          begin
            randList.Add(Explode(srcStrings.Strings[I], ';', 1));
          end;
        end;
        WriteLn;

        for I := 0 to 9 do
          WriteLn('Gewinner: ' + randList.Strings[Random(randList.Count)]);
        ReadLn;
      finally
        FreeAndNil(srcFile);
        srcStrings.Free;
        randList.Free;
      end;
Mit den gekürzten Summen, habe ich allerdings schon eine Speicherbelegung von mehr als 6GB und es wird ausgelagert.
Versuche ich das ganze mit den Originaldaten, friert mein System nach etwa 30 Sekunden ein und ... ich brauch' gar nicht weiter reden.

Also, über eure Hilfe wie ich diese Daten vernünftig verarbeiten kann wäre ich echt dankbar.

Ach so, die Funktion "Explode" holt mir die Komma-Separierten Daten aus der CSV (Kunde;Summe [oder auch Gewichtung]).

Gruß
Stefan
Stefan
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#2

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:40
Ok. Angenommen, Du hast 3 Kunden (A,B,C), mit 1,2 und 3 Euronen. Die einfachste Lösung wäre ja die, einfach eine Liste zu erstellen, in der ein Kunde so oft vorkommt, wie er Geld eingezahlt hat (wasndas für ein Deutsch?). Egal. Also die Liste wäre: A,B,B,C,C,C. Das sind 6 Einträge. Nun eine Zufallszahl z zwischen 1 und 6 und dann einfach den Kunden an der Stelle z in der Liste auslesen.

Bei deiner Anzahl ist das vielleicht ein wenig viel. Also machen wir es einfacher. Sei K die Liste der Kunden und E die Liste der Einzahlungen, sodass Kunde K[i] E[i] Euro eingezahlt hat. Sei ferner S die Summe aller Einzahlungen. Dann bildest Du eine Zufallszahl Z im Bereich (1..S). Gewonnen hat der Kunde K[i], für denn die Summe der Einzahlungen E[1]..E[i-1] < Z mit maximalem i ist. D.h. E[1]+...+E[i-1]<Z aber E[1]+...+E[i]>=Z

Beispiel: siehe oben:
Z=1. Gewonnen hat A, denn E[1]>=1;
Z=2. Gewonnen hat B, denn E[1]<2 aber E[1]+E[2] >= 2;
Z=3. Gewonnen hat B, denn E[1]<3 aber E[1]+E[2] >= 3;
Z=4. Gewonnen hat C, denn E[1]+E[2]<4 aber E[1]+E[2]+E[3] >= 4;
Z=5. Gewonnen hat C, denn E[1]+E[2]<5 aber E[1]+E[2]+E[3] >= 5;
Z=6. Gewonnen hat C, denn E[1]+E[2]<6 aber E[1]+E[2]+E[3] >= 6;

Wie man sieht, entspricht die Gewinnwahrscheinlichkeit eines Kunden exakt seiner eingezahlten Summe.

Delphi-Quellcode:
Function AndTheWinnerIs (K : KundeListe; E : EinzahlungsListe) : TKunde;
Var
  i, theWinner, Summe : Integer;
  
Begin
  Summe := E.Summe; // Summe aller Einzahlungen
  theWinner := Random (Summe) + 1;
  i := 0;
  While theWinner>E[i] do begin
     dec (theWinner, E[i]);
     inc(i);
  end;
  result := K[i]
End;
Noch besser ist jedoch dieses Verfahren:
Delphi-Quellcode:
Function AndTheWinnerIs(K : KundeListe; E : EinzahlungsListe) : TKunde;
Begin
  Result := 'Dejan Vu';
End;
Ich schicke Dir meine Kontoverbindung per PN

Geändert von Dejan Vu (18. Jun 2014 um 07:43 Uhr)
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#3

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:42
Hier mal mein Code der zwar funktioniert, aber nur wenn ich die Summen um den Faktor 100 dividiere.
Summen? Wo sind da Summen? Außerdem sehe ich noch nicht einmal Zahlen, sondern bis auf die Schleifenindices nur Strings.

Zahlen werden als Zahlen gespeichert und verarbeitet! Alles andere ist Zeit- und Speicherplatzverschwendung.

PS1: Man dividiert nicht um Faktoren, noch nicht einmal durch Faktoren. Faktoren sind Teile von Produkten.

PS2: Bei (Fließkomma-)Zahlen belegen übrigens die Zahlen selbst und die durch 100 dividierten den gleichen Platz, nämlich 4 bzw. 8 Byte.

Geändert von gammatester (18. Jun 2014 um 07:45 Uhr)
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.754 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:47
Hallo Stefan,

so wie ich das sehe, hälts Du die Daten dreimal im Speicher.
Als srcFile (TStringStream) als srcStrings (TStringList) and
als randlist (TStringList).

Warum liest Du die Datei nicht direkt in die StringList ein?
Warum gibts Du nicht srcFile frei nachdem Du die Daten an die StringList übergeben hast?


Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.994 Beiträge
 
Delphi 12 Athens
 
#5

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:51
Was bedeutet: "die Gewinnchance um 1 erhöhen"?

Soll jeder eingezahlte Euro von allen Kunden die gleiche Gewinnchance haben?

Dann würde ich erstmal die Gesamtsumme der Euros (G) ermitteln. Dabei musst du nur aufpassen, daß du beim Addieren keinen Integer-Überlauf erzeugst. Aus dieser Gesamtsumme ermittelst du dann eine Gewinnzahl (1..G). Danach durchläufst du die Eingabedatei nochmal, addierst alle Einzahlungen auf bis die Gewinnzahl erreicht bzw. überschritten wird. Der gerade eingelesene Kunde ist dann der Gewinner.

Wenn du mehrere (z.B. 10) Gewinner brauchst, kommt es darauf an, ob ein Kunde mehrmals gewinnen kann. Ist dies der Fall, kannst du gleich 10 Gewinnzahlen ermitteln und sortieren und das in einem Durchlauf erledigen. Andernfalls nimmst du nach jedem Gewinn den Kunden aus der Liste und führst das gesamte Verfahren mit den verbleibenden Kunden nochmal durch.

Das ist in etwa damit vergleichbar, als wenn jeder Kunde für jeden Euro ein Los in die Trommel geworfen hat.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#6

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 07:55
Dann würde ich erstmal die Gesamtsumme der Euros (G) ermitteln. Dabei musst du nur aufpassen, daß du beim Addieren keinen Integer-Überlauf erzeugst. Aus dieser Gesamtsumme ermittelst du dann eine Gewinnzahl (1..G). Danach durchläufst du die Eingabedatei nochmal, addierst alle Einzahlungen auf bis die Gewinnzahl erreicht bzw. überschritten wird. Der gerade eingelesene Kunde ist dann der Gewinner.
Inwieweit unterscheidet sich das von meiner Lösung (Post #2)?
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#7

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 08:19
Inwieweit unterscheidet sich das von meiner Lösung (Post #2)?
Ist doch offensichtlich: Uwe bittet nicht darum, als Gewinner eingetragen zu werden
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.994 Beiträge
 
Delphi 12 Athens
 
#8

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 08:22
Dann würde ich erstmal die Gesamtsumme der Euros (G) ermitteln. Dabei musst du nur aufpassen, daß du beim Addieren keinen Integer-Überlauf erzeugst. Aus dieser Gesamtsumme ermittelst du dann eine Gewinnzahl (1..G). Danach durchläufst du die Eingabedatei nochmal, addierst alle Einzahlungen auf bis die Gewinnzahl erreicht bzw. überschritten wird. Der gerade eingelesene Kunde ist dann der Gewinner.
Inwieweit unterscheidet sich das von meiner Lösung (Post #2)?
Nur in der Implementierung.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Bambuti2000
Bambuti2000

Registriert seit: 11. Okt 2007
Ort: Troisdorf
44 Beiträge
 
Delphi XE2 Architect
 
#9

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 09:33
Wunderbar, danke für die schnellen Antworten.

Besonderen Dank an Dejan Vu.
Wenn man sich das dann mal richtig überlegt, wird es auch klar und simpel.

Ich habe natürlich umgehend die Berechnung umgesetzt.
Das einzige was ich noch nicht so ganz verstehe ist
Zitat:
theWinner := Random (Summe) + 1;
warum +1 addiert wird.

Gruß
Stefan
Stefan
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#10

AW: Zufallsgenerator mit Gewichtung (aber mit sehr großen Datenmengen)

  Alt 18. Jun 2014, 09:36
Schau dir doch einfach mal die Online-Hilfe zu Random an:

In Delphi gibt Random eine Zufallszahl im Bereich 0 <= X < Range zurück.

Na, leuchtet's bereits?

Wenn nicht, dann schau dir mal im Debugger die Resultate an, wenn du bei Random als X-Wert z.B. 1 eingibst ... Jetzt sollte es aber deutlich leuchten bei dir ...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:37 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz