Feedback

C# - Zufallszahen mit verschiedenen Wahrscheinlichkeiten

Veröffentlicht von am 1/1/2015
(0 Bewertungen)
Mit dieser Klasse kann man Zufallszahlen mit verschiedenen Wahrscheinlichkeiten erzeugen.
Bsp.:
1 ==> 0.4
2 ==> 0.3
3 ==> 0.3
ACHTUNG! Man sollte nicht alle Wahrscheinlichkeiten angeben, auch wenn sie in der Summe 1 ergeben. Bei mir ist ein Wert vorgekommen, der nahe 0 war. Dieser Fehler kann auftreten. Um das zu vermeiden sollte höchstens alle Wahrscheinlichkeiten eintragen, außer eine. Die Wahrscheinlichkeit wird für die übrigen Zahlen automatisch ermittelt und gleichmäßig auf die übrigen Zahlen aufgeteilt.
Im Beispiel würde es dann ausreichen, die 1 anzugeben. Für 2, 3 bleiben 0.6, also für jeden 0.3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassLibrary1
{
    public class RandomP
    {
        System.Random rnd = new System.Random();
        public RandomP(List<KeyValuePair<int, double>> probabilities, int min, int max)
        {
            double P = 1;                                                                                                      //Restwahrscheinlichkeit
            int[] Keys = new int[probabilities.Capacity];
            int iL1 = 0;
            foreach (KeyValuePair<int, double> el in probabilities)
            {
                P -= el.Value;
                Keys[iL1] = el.Key;
                iL1++;
            }
            if (P < 0 || ((max - min + 1) == probabilities.Capacity && P > 0))
            { throw new Exception("Die Summe aller Wahrscheinlichkeiten muss 1 betragen!"); }
            else if (P > 0 && P < 1)
            {
                double PKey = P / (max - min - probabilities.Capacity);                                                        //Einzelwahrscheinlichkeit für übrige Zahlen
                List<KeyValuePair<int, double>> unsorted = new List<KeyValuePair<int, double>>(max - min + 1) { };
                for (int i = 0; i != unsorted.Capacity; i++)
                {
                    if (Keys.Contains(min + i))
                    {
                        int iL2 = 0;
                        foreach (KeyValuePair<int, double> el in probabilities)
                        {
                            if (el.Key == min + i)
                            { break; }
                            iL2++;
                        }
                        unsorted.Insert(i, new KeyValuePair<int, double>(min + i, probabilities[iL2].Value));
                    }
                    else
                    {
                        unsorted.Insert(i, new KeyValuePair<int, double>(min + i, PKey));
                    }
                }
                Probabilities = unsorted;
            }
            else { Probabilities = probabilities; }
            Comparer<int, double> compare = new Comparer<int, double>();
            Probabilities.Sort(compare);                                                                                        //Liste sortieren
        }

        List<KeyValuePair<int, double>> Probabilities
        { get; set; }

        public int NextInt()                                                                                                    //Zufallszahl bestimmen
        {
            double p = rnd.NextDouble();
            double cummulativ = 0;
            int Out = 0;
            foreach (KeyValuePair<int, double> el in Probabilities)
            {
                cummulativ += el.Value;
                if (p < cummulativ)
                {
                    Out = el.Key;
                    break;
                }
            }
            return Out;
        }

        class Comparer<TKey, TValue> : IComparer<KeyValuePair<TKey, TValue>> where TValue : IComparable
        {
            public int Compare(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
            {
                if (x.Value == null)
                {
                    if (y.Value == null)
                    { return 0; }
                    else
                    { return -1; }
                }
                else
                {
                    if (y.Value == null)
                    { return 1; }
                    else
                    {
                        return x.Value.CompareTo(y.Value);
                    }
                }
            }
        }
    }
}

Abgelegt unter Zufall, Random, Wahrscheinlichkeit.

2 Kommentare zum Snippet

Gwinn schrieb am 1/8/2015:
Hey,
das mit den sich wiederholenden zahlen kannst du einfach vermeiden, indem du 'rnd' als Feld deiner Klasse einmal erstellst und nicht jedes Mal in der Funktion NextInt()...
Fuzzi59 schrieb am 1/9/2015:
Stimmt die systemeigene Zufallsklasse (Random) muss global sein und nicht jedes mal neu erstellt werden. Danke für den Hinweis, ich werde es gleich ändern.
 

Logge dich ein, um hier zu kommentieren!