die aufgabenstellung ist extrem einfach: ich möchte aus einem array ein element zufällig auswählen. der haken daran ist, dass jedes element eine andere gewichtung hat,
[...]
das problem ist jedoch, dass diese lösung 1. extrem unschön ist und 2. für meine anwendung nicht möglich ist, da mein array nicht nur aus 4, sondern aus 100k elementen besteht. das würde den speicher sprengen. ;)
Eine speicherschonende Methode wäre folgende:
- Wähle ein Element i gleichverteilt-zufällig aus
- Bestimme den Quotienten q = random() / gewichtung[i]
- Wenn q<1, dann wähle das Element *wirklich* aus,
ansonsten: Wiederholung bei Punkt 1
IMHO hat die Methode einen Namen wie 'Acceptance-Reject method'.
Voraussetzung ist natürlich, dass die Summe aller Gewichtungen 1 ist
(andernfalls muss entsprechend normiert werden).
Das Problem dabei ist, dass die Anzahl erforderlicher
Wiederholungen, bis ein Element dann wirklich mal akzeptiert wird,
sehr groß werden kann und die Sache dadurch langsam wird. Das
gilt vor allem dann, wenn einige wenige Array-Elemente eine
sehr große Gewichtung (und dafür die anderen eine entsprechend
kleine Gewichtung) haben.
Eine Alternative: Bilde ein zweites, gleichgroßes Array, in
dem sukzessive die Summe der Gewichtungen gespeichert wird.
Beispiel in C-Syntax (A1[] sei das ursprüngliche Array, A2[] das zweite Array mit den Gewichtungs-Summen, gew[] seien die Gewichtungen):
double sum_gew = 0.0;
for(i=0; i<length; ++i) {
sum_gew += gew[i];
A2[i] = sum_gew;
}
double r = random();
int i=0;
while(r>A2[i]) ++i;
int iselected = i;
Diese Methode ist vermutlich etwas schneller, erfordert jedoch
Speicherplatz für ein zweites, gleichgroßes Array mit
Fließkommazahlen.Was jetzt wichtiger ist - Speicherplatz
oder Performance - musst Du abwägen...
MfG
Andreas