3 Stimmen

Wie erstellt man eine ungleichmäßige Bereichsnummer-Zufallsfunktion?

Wir wissen, dass die klassische Bereichs-Zufallsfunktion wie folgt aussieht:

public static final int random(final int min, final int max) {
    Random rand = new Random();
    return min + rand.nextInt(max - min + 1);  // +1 für die Einbeziehung des Maximums
}

Ich möchte einen Algorithmus erstellen, um eine Zahl im Bereich von 1..10 zufällig zu generieren, aber mit ungleichen Wahrscheinlichkeiten wie folgt:
1) 1,2,3 -> 3/6 (1/2)
2) 4,5,6,7 -> 1/6
3) 8,9,10 -> 2/6 (1/3)

Dies bedeutet, dass die Funktion eine 1/2-Chance hat, eine Zahl zwischen 1 und 3 zurückzugeben, eine 1/6-Chance, eine Zahl zwischen 4 und 7 zurückzugeben, und eine 1/3-Chance, eine Zahl zwischen 8 und 10 zurückzugeben.

Weiß jemand den Algorithmus?

UPDATE:
Eigentlich dient der Bereich von 1..10 nur als Beispiel. Die Funktion, die ich erstellen möchte, würde für beliebige Zahlenbereiche gelten, wie z.B. 1..10000, aber die Regel bleibt dieselbe: 3/6 für den oberen Bereich (30% Anteil), 1/6 für den mittleren Bereich (nächste 40% Anteil) und 2/6 für den unteren Bereich (letzten 30% Anteil).

0voto

null Punkte 8088

Wie angefordert, hier ist mein Code (basierend auf izomorphius's Code), der hoffentlich mein Problem löst:

private static Random rand = new Random();

public static int rangeRandom(final int min, final int max) {
    return min + rand.nextInt(max - min + 1);  // +1 für die Inklusion von max
}

/**
 * 
 * @param min           Die minimale Bereichszahl
 * @param max           Die maximale Bereichszahl
 * @param weights       Array mit verteilten Gewichtswerten. Die Summe der Werte muss 1,0 betragen
 * @param chances       Array mit verteilten Chance-Werten. Die Arraylänge muss mit den Gewichten übereinstimmen und die Summe der Werte muss 1,0 betragen
 * @return              Zufallszahl
 * @throws Exception    Wahrscheinlich sollte eigene Ausnahme erstellt werden, aber ich benutze default Exception für Einfachheit
 */
public static int weightedRangeRandom(final int min, final int max, final float[] weights, final float[] chances) throws Exception {
    // einige Validierungen
    if (weights.length != chances.length) {
        throw new Exception("Länge von Gewicht & Chance müssen gleich sein");
    }

    int len = weights.length;

    float sumWeight = 0, sumChance = 0;
    for (int i=0; i

`

Beispiel für die Verwendung:

int result = weightedRangeRandom(1, 10, new float[] {0,3f, 0,4f, 0,3f}, 
    new float[] {1f/2, 1f/6, 1f/3});

Der Code könnte noch Ungenauigkeiten bei der Verteilung der Teilebereichsgrenzen (tMin & tMax) aufweisen, aufgrund der Division durch Gewicht, die zu einem Dezimalwert führt. Aber ich denke, das ist unvermeidlich, weil die Bereichszahlen Ganzzahlen sind.

Einige Eingabevalidierungen könnten erforderlich sein, aber ich habe sie der Einfachheit halber weggelassen.

Kritik, Korrekturen und Reviews sind herzlich willkommen :)

`

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X